frontend & backend update
1298
_ide_helper.php
@@ -5,6 +5,8 @@ namespace App\Http\Controllers\Admin;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\GatewayCollection;
|
||||
use App\Http\Resources\GatewayResource;
|
||||
use App\Http\Resources\InvoiceCollection;
|
||||
use App\Invoice;
|
||||
use App\PaymentGateway;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -33,6 +35,19 @@ class GatewayController extends Controller
|
||||
return new GatewayResource($gateway);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single payment gateway by slug
|
||||
*
|
||||
* @param $slug
|
||||
* @return InvoiceCollection
|
||||
*/
|
||||
public function show_transactions($slug)
|
||||
{
|
||||
return new InvoiceCollection(
|
||||
Invoice::where('provider', $slug)->get()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update payment gateway options
|
||||
*
|
||||
|
||||
@@ -8,12 +8,21 @@ use App\Http\Resources\PlanResource;
|
||||
use App\Http\Resources\UserResource;
|
||||
use App\Http\Resources\UsersCollection;
|
||||
use App\Plan;
|
||||
use App\Services\StripeService;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Rinvex\Subscriptions\Models\PlanFeature;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plans
|
||||
*
|
||||
@@ -22,7 +31,7 @@ class PlanController extends Controller
|
||||
public function index()
|
||||
{
|
||||
return new PlanCollection(
|
||||
app('rinvex.subscriptions.plan')->all()
|
||||
$this->stripe->getPlans()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,7 +44,7 @@ class PlanController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
return new PlanResource(
|
||||
app('rinvex.subscriptions.plan')->find($id)
|
||||
$this->stripe->getPlan($id)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,26 +56,9 @@ class PlanController extends Controller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$plan = app('rinvex.subscriptions.plan')->create([
|
||||
'description' => $request->input('attributes.description'),
|
||||
'price' => $request->input('attributes.price'),
|
||||
'name' => $request->input('attributes.name'),
|
||||
'currency' => 'USD',
|
||||
'invoice_period' => 1,
|
||||
'sort_order' => 1,
|
||||
'signup_fee' => 0,
|
||||
]);
|
||||
|
||||
// Create multiple plan features at once
|
||||
$plan->features()->saveMany([
|
||||
new PlanFeature([
|
||||
'name' => 'Storage capacity',
|
||||
'value' => $request->input('attributes.capacity'),
|
||||
'sort_order' => 1
|
||||
]),
|
||||
]);
|
||||
|
||||
return new PlanResource($plan);
|
||||
return new PlanResource(
|
||||
$this->stripe->createPlan($request)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,18 +70,24 @@ class PlanController extends Controller
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
// TODO: validation request
|
||||
$plan = app('rinvex.subscriptions.plan')->find($id);
|
||||
|
||||
if ($request->name === 'capacity') {
|
||||
$plan->getFeatureBySlug('storage-capacity')->update(['value' => $request->value]);
|
||||
} else {
|
||||
$plan->update(make_single_input($request));
|
||||
}
|
||||
$this->stripe->updatePlan($request, $id);
|
||||
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete plan
|
||||
*
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$this->stripe->deletePlan($id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscriptions
|
||||
*
|
||||
|
||||
@@ -258,11 +258,6 @@ class EditItemsController extends Controller
|
||||
return Demo::upload($request);
|
||||
}
|
||||
|
||||
// Check if user can upload
|
||||
if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100) {
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
}
|
||||
|
||||
// Check permission to upload for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
|
||||
@@ -4,19 +4,32 @@ namespace App\Http\Controllers\General;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PricingCollection;
|
||||
use App\Services\StripeService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PricingController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active plans
|
||||
*
|
||||
* @return PricingCollection
|
||||
*/
|
||||
public function index() {
|
||||
|
||||
return new PricingCollection(
|
||||
app('rinvex.subscriptions.plan')->where('is_active', 1)->get()
|
||||
public function index()
|
||||
{
|
||||
$collection = new PricingCollection(
|
||||
$this->stripe->getActivePlans()
|
||||
);
|
||||
|
||||
return $collection->sortBy('product.metadata.capacity')
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
}
|
||||
|
||||
107
app/Http/Controllers/User/PaymentCardsController.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PaymentCardCollection;
|
||||
use App\Http\Resources\PaymentCardResource;
|
||||
use App\Http\Resources\PaymentDefaultCardResource;
|
||||
use App\Services\PaymentService;
|
||||
use App\UserCard;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Cashier\PaymentMethod;
|
||||
|
||||
class PaymentCardsController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var PaymentService
|
||||
*/
|
||||
private $payment;
|
||||
|
||||
/**
|
||||
* PaymentCardsController constructor.
|
||||
*/
|
||||
public function __construct(PaymentService $payment)
|
||||
{
|
||||
$this->payment = $payment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update card detail
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Update DefaultPayment Method
|
||||
$user->updateDefaultPaymentMethod($id);
|
||||
|
||||
// Sync default payment method
|
||||
$user->updateDefaultPaymentMethodFromStripe();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete user credit card
|
||||
*
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Get payment method
|
||||
$paymentMethod = $user->findPaymentMethod($id);
|
||||
|
||||
// Delete payment method
|
||||
$paymentMethod->delete();
|
||||
|
||||
// Sync default payment method
|
||||
$user->updateDefaultPaymentMethodFromStripe();
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user payment methods sorted by default and others
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function payment_methods()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Get default payment method
|
||||
$defaultPaymentMethodObject = $user->defaultPaymentMethod();
|
||||
|
||||
$defaultPaymentMethod = $defaultPaymentMethodObject instanceof PaymentMethod
|
||||
? $defaultPaymentMethodObject->asStripePaymentMethod()
|
||||
: $defaultPaymentMethodObject;
|
||||
|
||||
// filter payment methods without default payment
|
||||
$paymentMethods = $user->paymentMethods()->filter(function ($paymentMethod) use ($defaultPaymentMethod) {
|
||||
return $paymentMethod->id !== $defaultPaymentMethod->id;
|
||||
});
|
||||
|
||||
// Get payment methods
|
||||
$paymentMethodsMapped = $paymentMethods->map(function ($paymentMethod) {
|
||||
return $paymentMethod->asStripePaymentMethod();
|
||||
})->values()->all();
|
||||
|
||||
if (is_null($paymentMethodsMapped) && is_null($paymentMethodsMapped)) {
|
||||
return [
|
||||
'default' => null,
|
||||
'others' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'default' => $defaultPaymentMethod instanceof PaymentMethod
|
||||
? new PaymentCardResource($defaultPaymentMethod)
|
||||
: new PaymentDefaultCardResource($defaultPaymentMethod),
|
||||
'others' => new PaymentCardCollection($paymentMethodsMapped),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -3,53 +3,82 @@
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Subscription\StoreUpgradeAccountRequest;
|
||||
use App\Http\Resources\UserSubscription;
|
||||
use App\Invoice;
|
||||
use App\Services\PaymentService;
|
||||
use App\Services\StripeService;
|
||||
use Auth;
|
||||
use Cartalyst\Stripe\Exception\CardErrorException;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Cashier\Exceptions\IncompletePayment;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class SubscriptionController extends Controller
|
||||
{
|
||||
private $stripe;
|
||||
|
||||
/**
|
||||
* SubscriptionController constructor.
|
||||
* @param $payment
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate setup intent
|
||||
*
|
||||
* @return \Stripe\SetupIntent
|
||||
*/
|
||||
public function stripe_setup_intent()
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Create stripe customer if not exist
|
||||
$user->createOrGetStripeCustomer();
|
||||
|
||||
// Return setup intent
|
||||
return $user->createSetupIntent();
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
return new UserSubscription(
|
||||
Auth::user()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade account to subscription
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
* @param StoreUpgradeAccountRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function upgrade(Request $request)
|
||||
public function upgrade(StoreUpgradeAccountRequest $request)
|
||||
{
|
||||
// TODO: validation request
|
||||
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Get requested plan
|
||||
$plan = app('rinvex.subscriptions.plan')
|
||||
->find($request->input('plan.data.id'));
|
||||
$plan = $this->stripe->getPlan($request->input('plan.data.id'));
|
||||
|
||||
// Check if user have subscription
|
||||
if ($user->activeSubscriptions()->count() !== 0) {
|
||||
// Set user billing
|
||||
$user->setBilling($request->input('billing'));
|
||||
|
||||
// Get old subscription
|
||||
$subscription = $user->subscription('main');
|
||||
|
||||
// Change subscription plan
|
||||
$subscription->changePlan($plan);
|
||||
|
||||
} else {
|
||||
|
||||
// Create subscription
|
||||
$user->newSubscription('main', $plan);
|
||||
}
|
||||
// Make subscription
|
||||
$this->stripe->createOrReplaceSubscription($request, $user);
|
||||
|
||||
// Update user storage limit
|
||||
$user->settings()->update([
|
||||
'storage_capacity' => $plan->features->first()->value
|
||||
'storage_capacity' => $plan['product']['metadata']['capacity']
|
||||
]);
|
||||
|
||||
// Store invoice
|
||||
Invoice::create(
|
||||
get_invoice_data($user, $plan)
|
||||
);
|
||||
Invoice::create(get_invoice_data($user, $plan, 'stripe'));
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
@@ -57,15 +86,25 @@ class SubscriptionController extends Controller
|
||||
/**
|
||||
* Cancel Subscription
|
||||
*
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function cancel() {
|
||||
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
public function cancel()
|
||||
{
|
||||
// Cancel subscription
|
||||
$user->subscription('main')->cancel();
|
||||
Auth::user()->subscription('main')->cancel();
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume Subscription
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function resume()
|
||||
{
|
||||
// Resume subscription
|
||||
Auth::user()->subscription('main')->resume();
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,14 @@ function get_invoice_number()
|
||||
}
|
||||
}
|
||||
|
||||
function get_invoice_data($user, $plan)
|
||||
/**
|
||||
* Get data to render in invoice tempalte
|
||||
* @param $user
|
||||
* @param $plan
|
||||
* @param $provider
|
||||
* @return array
|
||||
*/
|
||||
function get_invoice_data($user, $plan, $provider)
|
||||
{
|
||||
$subscription = $user->subscription('main');
|
||||
$order_number = get_invoice_number();
|
||||
@@ -36,15 +43,17 @@ function get_invoice_data($user, $plan)
|
||||
return [
|
||||
'token' => $token,
|
||||
'order' => $order_number,
|
||||
'provider' => $provider,
|
||||
'user_id' => $user->id,
|
||||
'plan_id' => $plan->id,
|
||||
'total' => $plan->price,
|
||||
'plan_id' => $plan['plan']['id'],
|
||||
'total' => $plan['plan']['amount'],
|
||||
'currency' => 'USD',
|
||||
'bag' => [
|
||||
[
|
||||
'description' => 'Subscription - ' . $plan->name,
|
||||
'date' => format_date($subscription->starts_at, '%d. %B. %Y') . ' - ' . format_date($subscription->ends_at, '%d. %B. %Y'),
|
||||
'amount' => $plan->price,
|
||||
'description' => 'Subscription - ' . $plan['product']['name'],
|
||||
//'date' => format_date($subscription->starts_at, '%d. %B. %Y') . ' - ' . format_date($subscription->ends_at, '%d. %B. %Y'),
|
||||
'date' => format_date(Carbon::now(),'%d. %B. %Y'),
|
||||
'amount' => $plan['plan']['amount'],
|
||||
]
|
||||
],
|
||||
'seller' => [
|
||||
@@ -282,15 +291,21 @@ function get_storage_fill_percentage($used, $capacity)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user capacity fill percentage
|
||||
* Get user capacity fill by percentage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function user_storage_percentage()
|
||||
function user_storage_percentage($id, $additionals = null)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$user = \App\User::findOrFail($id);
|
||||
|
||||
return get_storage_fill_percentage($user->used_capacity, $user->settings->storage_capacity);
|
||||
$used = $user->used_capacity;
|
||||
|
||||
if ($additionals) {
|
||||
$used = $user->used_capacity + $additionals;
|
||||
}
|
||||
|
||||
return get_storage_fill_percentage($used, $user->settings->storage_capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
23
app/Http/Helpers/subscription.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Check if current user subscribed plan is highest
|
||||
*
|
||||
* @param $id
|
||||
* @param $subscribed_capacity
|
||||
* @return int
|
||||
*/
|
||||
function is_highest_plan($plan)
|
||||
{
|
||||
$plans = app('rinvex.subscriptions.plan')->all();
|
||||
|
||||
$unsubscribed = $plans->filter(function ($item) use ($plan) {
|
||||
return $item->id !== $plan->id;
|
||||
});
|
||||
|
||||
$capacities = $unsubscribed->map(function ($item) {
|
||||
return $item->features->first()->value;
|
||||
});
|
||||
|
||||
return max(Arr::flatten($capacities)) < $plan->features->first()->value ? 1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Subscription;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreUpgradeAccountRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
// Billings
|
||||
'billing' => 'required|array',
|
||||
'billing.billing_address' => 'required|string',
|
||||
'billing.billing_city' => 'required|string',
|
||||
'billing.billing_country' => 'required|string',
|
||||
'billing.billing_name' => 'required|string',
|
||||
'billing.billing_phone_number' => 'required|string',
|
||||
'billing.billing_postal_code' => 'required|string',
|
||||
'billing.billing_state' => 'required|string',
|
||||
|
||||
// Payment
|
||||
'payment' => 'required|array',
|
||||
'payment.type' => 'required|string',
|
||||
'payment.meta' => 'required|sometimes|array',
|
||||
'payment.meta.pm' => 'required|sometimes|string',
|
||||
|
||||
// Plan
|
||||
'plan.data' => 'required|array',
|
||||
'plan.data.attributes' => 'required|array',
|
||||
'plan.data.attributes.capacity' => 'required|digits_between:1,9',
|
||||
'plan.data.attributes.capacity_formatted' => 'required|string',
|
||||
'plan.data.attributes.currency' => 'required|string',
|
||||
'plan.data.attributes.description' => 'required|string',
|
||||
'plan.data.attributes.name' => 'required|string',
|
||||
'plan.data.attributes.price' => 'required|string',
|
||||
'plan.data.id' => 'required|string',
|
||||
'plan.data.type' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -19,15 +19,16 @@ class GatewayResource extends JsonResource
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'gateways',
|
||||
'attributes' => [
|
||||
'status' => $this->status,
|
||||
'sandbox' => $this->sandbox,
|
||||
'name' => $this->name,
|
||||
'slug' => $this->slug,
|
||||
'logo' => $this->logo,
|
||||
'client_id' => $this->client_id,
|
||||
'secret' => $this->secret,
|
||||
'webhook' => $this->webhook,
|
||||
'optional' => $this->optional,
|
||||
'status' => $this->status,
|
||||
'sandbox' => $this->sandbox,
|
||||
'name' => $this->name,
|
||||
'slug' => $this->slug,
|
||||
'logo' => $this->logo,
|
||||
'client_id' => $this->client_id,
|
||||
'secret' => $this->secret,
|
||||
'webhook' => $this->webhook,
|
||||
'payment_processed' => $this->payment_processed,
|
||||
'optional' => $this->optional,
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
23
app/Http/Resources/PaymentCardCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PaymentCardCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PaymentCardResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Resources/PaymentCardResource.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PaymentCardResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this['id'],
|
||||
'type' => 'payment_method',
|
||||
'attributes' => [
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $this['id'],
|
||||
'brand' => strtolower($this['card']['brand']),
|
||||
'last4' => $this['card']['last4'],
|
||||
'exp_month' => $this['card']['exp_month'],
|
||||
'exp_year' => $this['card']['exp_year'],
|
||||
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
|
||||
'status' => 'active',
|
||||
'default' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Resources/PaymentDefaultCardResource.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PaymentDefaultCardResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this['id'],
|
||||
'type' => 'payment_method',
|
||||
'attributes' => [
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $this['id'],
|
||||
'brand' => isset($this['brand']) ? strtolower($this['brand']) : strtolower($this['card']['brand']),
|
||||
'last4' => isset($this['last4']) ? $this['last4'] : $this['card']['last4'],
|
||||
'exp_month' => isset($this['exp_month']) ? $this['exp_month'] : $this['card']['exp_month'],
|
||||
'exp_year' => isset($this['exp_year']) ? $this['exp_year'] : $this['card']['exp_year'],
|
||||
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
|
||||
'status' => 'active',
|
||||
'default' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -16,19 +16,18 @@ class PlanResource extends JsonResource
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'id' => $this['plan']['id'],
|
||||
'type' => 'plans',
|
||||
'attributes' => [
|
||||
'subscribers' => $this->subscriptions->count(),
|
||||
'status' => $this->is_active,
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'price' => $this->price,
|
||||
'capacity_formatted' => format_gigabytes($this->features->first()->value),
|
||||
'capacity' => $this->features->first()->value,
|
||||
'created_at_formatted' => format_date($this->created_at),
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
'subscribers' => $this['plan']['aggregate_usage'],
|
||||
'status' => $this['plan']['active'],
|
||||
'name' => $this['product']['name'],
|
||||
'description' => $this['product']['description'],
|
||||
'price' => $this['plan']['amount'],
|
||||
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
|
||||
'capacity' => $this['product']['metadata']['capacity'],
|
||||
'created_at_formatted' => format_date($this['plan']['created']),
|
||||
'created_at' => $this['plan']['created'],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -3,28 +3,29 @@
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
|
||||
class PricingResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'id' => $this['plan']['id'],
|
||||
'type' => 'plans',
|
||||
'attributes' => [
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'price' => $this->price,
|
||||
'capacity_formatted' => format_gigabytes($this->features->first()->value),
|
||||
'capacity' => (int) $this->features->first()->value,
|
||||
'currency' => 'USD',
|
||||
'name' => $this['product']['name'],
|
||||
'description' => $this['product']['description'],
|
||||
'price' => Cashier::formatAmount($this['plan']['amount']),
|
||||
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
|
||||
'capacity' => (int) $this['product']['metadata']['capacity'],
|
||||
'currency' => 'USD',
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\Services\StripeService;
|
||||
use App\User;
|
||||
use Cartalyst\Stripe\Api\PaymentMethods;
|
||||
use Faker\Factory;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@@ -27,16 +30,14 @@ class UserResource extends JsonResource
|
||||
'email' => env('APP_DEMO') ? $faker->email : $this->email,
|
||||
'avatar' => $this->avatar,
|
||||
'role' => $this->role,
|
||||
'subscription' => $this->subscribed('main'),
|
||||
'created_at_formatted' => format_date($this->created_at, '%d. %B. %Y'),
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
]
|
||||
],
|
||||
'relationships' => [
|
||||
'subscription' => $this->activeSubscriptions()->count() !== 0
|
||||
? new UserSubscription($this->subscription('main'))
|
||||
: null,
|
||||
'settings' => [
|
||||
'settings' => [
|
||||
'data' => [
|
||||
'id' => (string)$this->settings->id,
|
||||
'type' => 'settings',
|
||||
@@ -51,14 +52,14 @@ class UserResource extends JsonResource
|
||||
]
|
||||
]
|
||||
],
|
||||
'storage' => [
|
||||
'storage' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'storage',
|
||||
'attributes' => $this->storage
|
||||
]
|
||||
],
|
||||
'favourites' => [
|
||||
'favourites' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'folders_favourite',
|
||||
@@ -67,7 +68,7 @@ class UserResource extends JsonResource
|
||||
],
|
||||
],
|
||||
],
|
||||
'tree' => [
|
||||
'tree' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'folders_tree',
|
||||
@@ -76,6 +77,7 @@ class UserResource extends JsonResource
|
||||
],
|
||||
],
|
||||
],
|
||||
'payment_methods' => new PaymentCardCollection($this->payment_cards)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
@@ -14,21 +14,33 @@ class UserSubscription extends JsonResource
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
$active_subscription = $this->subscription('main')->asStripeSubscription();
|
||||
|
||||
// Get subscription details
|
||||
$subscription = $stripe->getPlan($this->subscription('main')->stripe_plan);
|
||||
|
||||
// Retrieve the timestamp from Stripe
|
||||
$current_period_end = $active_subscription["current_period_end"];
|
||||
$current_period_start = $active_subscription["current_period_start"];
|
||||
$canceled_at = $active_subscription["canceled_at"];
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'id' => $subscription['plan']['id'],
|
||||
'type' => 'subscription',
|
||||
'attributes' => [
|
||||
'active' => $this->active(),
|
||||
'canceled' => $this->canceled(),
|
||||
'name' => $this->plan->name,
|
||||
'capacity' => (int) $this->plan->features->first()->value,
|
||||
'capacity_formatted' => format_gigabytes($this->plan->features->first()->value),
|
||||
'slug' => $this->slug,
|
||||
'canceled_at' => format_date($this->created_at, '%d. %B. %Y'),
|
||||
'created_at' => format_date($this->created_at, '%d. %B. %Y'),
|
||||
'starts_at' => format_date($this->starts_at, '%d. %B. %Y'),
|
||||
'ends_at' => format_date($this->ends_at, '%d. %B. %Y'),
|
||||
/*'is_highest' => is_highest_plan($this->plan),*/
|
||||
'active' => $subscription['plan']['active'],
|
||||
'canceled' => $this->subscription('main')->cancelled(),
|
||||
'name' => $subscription['product']['name'],
|
||||
'capacity' => (int)$subscription['product']['metadata']['capacity'],
|
||||
'capacity_formatted' => format_gigabytes($subscription['product']['metadata']['capacity']),
|
||||
'slug' => $subscription['plan']['id'],
|
||||
'canceled_at' => format_date($canceled_at, '%d. %B. %Y'),
|
||||
'created_at' => format_date($current_period_start, '%d. %B. %Y'),
|
||||
'ends_at' => format_date($current_period_end, '%d. %B. %Y'),
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -197,14 +197,20 @@ class Editor
|
||||
*/
|
||||
public static function upload($request, $shared = null)
|
||||
{
|
||||
// Get user data
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// Get parent_id from request
|
||||
$folder_id = $request->parent_id === 0 ? 0 : $request->parent_id;
|
||||
$file = $request->file('file');
|
||||
|
||||
// Get user data
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
$user_storage_used = user_storage_percentage($user_id, $file->getSize());
|
||||
|
||||
// Check if user can upload
|
||||
if (config('vuefilemanager.limit_storage_by_capacity') && $user_storage_used >= 100) {
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
}
|
||||
|
||||
// File
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$filetype = get_file_type($file);
|
||||
|
||||
@@ -4,6 +4,43 @@ namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Invoice
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $token
|
||||
* @property string $order
|
||||
* @property string|null $provider
|
||||
* @property string $user_id
|
||||
* @property string $plan_id
|
||||
* @property array $seller
|
||||
* @property array $client
|
||||
* @property array $bag
|
||||
* @property string|null $notes
|
||||
* @property string $total
|
||||
* @property string $currency
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\User|null $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereBag($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereClient($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereCurrency($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereNotes($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereOrder($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice wherePlanId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereProvider($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereSeller($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereTotal($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Invoice extends Model
|
||||
{
|
||||
protected $guarded = [
|
||||
|
||||
@@ -4,6 +4,36 @@ namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\PaymentGateway
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $status
|
||||
* @property int $sandbox
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $logo
|
||||
* @property string|null $client_id
|
||||
* @property string|null $secret
|
||||
* @property string|null $webhook
|
||||
* @property string|null $optional
|
||||
* @property int|null $payment_processed
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereClientId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereLogo($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereOptional($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway wherePaymentProcessed($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSandbox($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSecret($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSlug($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereStatus($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereWebhook($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class PaymentGateway extends Model
|
||||
{
|
||||
protected $guarded = ['id'];
|
||||
|
||||
199
app/Services/PaymentService.php
Normal file
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
|
||||
use App\PaymentGateway;
|
||||
use App\User;
|
||||
use App\UserCard;
|
||||
use App\UserSettings;
|
||||
use Cartalyst\Stripe\Exception\CardErrorException;
|
||||
use Stripe;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class PaymentService
|
||||
{
|
||||
/**
|
||||
* PaymentService constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->stripe = Stripe::make(config('services.stripe.secret'), '2020-03-02');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and charge customer
|
||||
*
|
||||
* @param $request
|
||||
* @param $plan
|
||||
* @param $user
|
||||
*/
|
||||
public function getAndChargeCustomer($request, $plan, $user)
|
||||
{
|
||||
// Get Stripe Customer
|
||||
$customer = $this->findOrCreateStripeCustomer($user);
|
||||
|
||||
$paymentIntent = $this->stripe->paymentIntents()->create([
|
||||
'amount' => $plan->price,
|
||||
'currency' => 'USD',
|
||||
'payment_method_types' => [
|
||||
'card',
|
||||
],
|
||||
]);
|
||||
|
||||
dd($paymentIntent);
|
||||
|
||||
// Try charge customer
|
||||
try {
|
||||
if ($request->has('payment.meta.card_token')) {
|
||||
|
||||
// Register customer credit card
|
||||
$created_card = $this->registerStripeCreditCard($customer, $request->input('payment.meta.card_token'));
|
||||
|
||||
// Charge with created credit card
|
||||
/*$this->stripe->charges()->create([
|
||||
'description' => 'Subscription ' . $plan->name,
|
||||
'customer' => $customer['id'],
|
||||
'amount' => $plan->price,
|
||||
'currency' => 'USD',
|
||||
'source' => $created_card->card_id
|
||||
]);*/
|
||||
|
||||
} else {
|
||||
|
||||
// Charge with customer default creadit card
|
||||
$this->stripe->charges()->create([
|
||||
'description' => 'Subscription ' . $plan->name,
|
||||
'customer' => $customer['id'],
|
||||
'amount' => $plan->price,
|
||||
'currency' => 'USD',
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (CardErrorException $error) {
|
||||
|
||||
//dd($error);
|
||||
|
||||
// Remove previously registered card
|
||||
if (in_array($error->getErrorCode(), ['rejected_card', 'card_declined'])
|
||||
&& $request->has('payment.meta.card_token')
|
||||
&& isset($error->getRawOutput()['error']['charge'])) {
|
||||
|
||||
// Get charge
|
||||
$charge = $this->stripe->charges()->find($error->getRawOutput()['error']['charge']);
|
||||
|
||||
// Remove card from stripe
|
||||
$this->deleteStripeCard($user->settings->stripe_customer_id, $charge['payment_method']);
|
||||
|
||||
// Get card
|
||||
$error_card = UserCard::where('card_id', $charge['payment_method'])->first();
|
||||
|
||||
// Delete card
|
||||
$error_card->delete();
|
||||
}
|
||||
|
||||
throw new HttpException($error->getCode(), $error->getMessage());
|
||||
}
|
||||
|
||||
// Increase payment processed column
|
||||
PaymentGateway::where('slug', 'stripe')->first()->increment('payment_processed');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find or create stripe customer
|
||||
*
|
||||
* @param $user
|
||||
* @return array
|
||||
*/
|
||||
private function findOrCreateStripeCustomer($user)
|
||||
{
|
||||
// Get existing stripe customer
|
||||
if ($user->settings->stripe_customer_id) {
|
||||
|
||||
return $this->stripe->customers()->find($user->settings->stripe_customer_id);
|
||||
}
|
||||
|
||||
// Create new stripe costumer
|
||||
if (!$user->settings->stripe_customer_id) {
|
||||
|
||||
$customer = $this->stripe->customers()->create([
|
||||
'email' => $user->email,
|
||||
'name' => $user->name,
|
||||
'address' => [
|
||||
'city' => $user->settings->billing_city,
|
||||
'country' => $user->settings->billing_country,
|
||||
'line1' => $user->settings->billing_address,
|
||||
'state' => $user->settings->billing_state,
|
||||
'postal_code' => $user->settings->billing_postal_code,
|
||||
]
|
||||
]);
|
||||
|
||||
// Store user stripe_customer_id
|
||||
$user->settings()->update([
|
||||
'stripe_customer_id' => $customer['id']
|
||||
]);
|
||||
|
||||
return $customer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register stripe credit card
|
||||
*
|
||||
* @param $customer
|
||||
* @param $card_id
|
||||
* @return object
|
||||
*/
|
||||
private function registerStripeCreditCard($customer, $card_id)
|
||||
{
|
||||
// Register user card
|
||||
$card = $this->stripe->cards()->create($customer['id'], $card_id);
|
||||
|
||||
// Get user settings
|
||||
$user_settings = UserSettings::where('stripe_customer_id', $customer['id'])->first();
|
||||
|
||||
// Set default status
|
||||
$default_card = UserCard::where('user_id', $user_settings->user_id)->get()->count() > 0 ? 0 : 1;
|
||||
|
||||
// Store user card
|
||||
$card = UserCard::create([
|
||||
'user_id' => $user_settings->user_id,
|
||||
'status' => 'active',
|
||||
'default' => $default_card,
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $card['id'],
|
||||
'brand' => $card['brand'],
|
||||
'last4' => $card['last4'],
|
||||
'exp_month' => $card['exp_month'],
|
||||
'exp_year' => $card['exp_year'],
|
||||
]);
|
||||
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new default source from existing credit card
|
||||
*
|
||||
* @param $stripe_customer_id
|
||||
* @param $card_id
|
||||
*/
|
||||
public function setDefaultStripeCard($stripe_customer_id, $card_id)
|
||||
{
|
||||
$this->stripe->customers()->update($stripe_customer_id, [
|
||||
'default_source' => $card_id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete customer stripe credit card
|
||||
*
|
||||
* @param $stripe_customer_id
|
||||
* @param $card_id
|
||||
*/
|
||||
public function deleteStripeCard($stripe_customer_id, $card_id)
|
||||
{
|
||||
$this->stripe->cards()->delete($stripe_customer_id, $card_id);
|
||||
}
|
||||
}
|
||||
229
app/Services/StripeService.php
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Cashier\Exceptions\IncompletePayment;
|
||||
use Stripe;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class StripeService
|
||||
{
|
||||
/**
|
||||
* Stripe Service constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->stripe = Stripe::make(env('STRIPE_SECRET'), '2020-03-02');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default payment option or set new default payment
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrSetDefaultPaymentMethod($request, $user)
|
||||
{
|
||||
// Check payment method
|
||||
if (! $request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Get default payment
|
||||
return $user->defaultPaymentMethod()->paymentMethod;
|
||||
|
||||
} else if ( $request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod() ) {
|
||||
|
||||
// Set new payment
|
||||
return $user->addPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
|
||||
|
||||
} else if ( $request->has('payment.meta.pm') && ! $user->hasDefaultPaymentMethod() ) {
|
||||
|
||||
// Set new payment
|
||||
return $user->updateDefaultPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
|
||||
|
||||
} else {
|
||||
|
||||
throw new HttpException(400, 'Something went wrong.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new subscription or replace by new subscription
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @param $paymentMethod
|
||||
*/
|
||||
public function createOrReplaceSubscription($request, $user)
|
||||
{
|
||||
try {
|
||||
|
||||
// Get payment method
|
||||
$paymentMethod = $this->getOrSetDefaultPaymentMethod($request, $user);
|
||||
|
||||
// Check if user have subscription
|
||||
if ($user->subscribed('main')) {
|
||||
|
||||
// Change subscription plan
|
||||
$user->subscription('main')->skipTrial()->swap($request->input('plan.data.id'));
|
||||
|
||||
} else {
|
||||
|
||||
// Create subscription
|
||||
$user->newSubscription('main', $request->input('plan.data.id'))->create($paymentMethod);
|
||||
}
|
||||
|
||||
} catch (IncompletePayment $exception) {
|
||||
|
||||
throw new HttpException(400, 'We can\'t charge your card');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create plan
|
||||
*
|
||||
* @param $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function createPlan($request)
|
||||
{
|
||||
$product = $this->stripe->products()->create([
|
||||
'name' => $request->input('attributes.name'),
|
||||
'description' => $request->input('attributes.description'),
|
||||
'metadata' => [
|
||||
'capacity' => $request->input('attributes.capacity')
|
||||
]
|
||||
]);
|
||||
|
||||
$plan = $this->stripe->plans()->create([
|
||||
'id' => Str::slug($request->input('attributes.name')),
|
||||
'amount' => $request->input('attributes.price'),
|
||||
'currency' => 'USD',
|
||||
'interval' => 'month',
|
||||
'product' => $product['id'],
|
||||
]);
|
||||
|
||||
return compact('plan', 'product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update plan
|
||||
*
|
||||
* @param $request
|
||||
* @param $id
|
||||
*/
|
||||
public function updatePlan($request, $id)
|
||||
{
|
||||
$plan_colls = ['is_active', 'price'];
|
||||
$product_colls = ['name', 'description', 'capacity'];
|
||||
|
||||
$plan = $this->stripe->plans()->find($id);
|
||||
|
||||
// Update product
|
||||
if (in_array($request->name, $product_colls)) {
|
||||
|
||||
if ($request->name === 'capacity') {
|
||||
$this->stripe->products()->update($plan['product'], ['metadata' => ['capacity' => $request->value]]);
|
||||
}
|
||||
if ($request->name === 'name') {
|
||||
$this->stripe->products()->update($plan['product'], ['name' => $request->value]);
|
||||
}
|
||||
if ($request->name === 'description') {
|
||||
$this->stripe->products()->update($plan['product'], ['description' => $request->value]);
|
||||
}
|
||||
}
|
||||
|
||||
// Update plan
|
||||
if (in_array($request->name, $plan_colls)) {
|
||||
|
||||
if ($request->name === 'is_active') {
|
||||
$this->stripe->plans()->update($id, ['active' => $request->value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan details
|
||||
*
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlan($id)
|
||||
{
|
||||
$plan = $this->stripe->plans()->find($id);
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
return compact('plan', 'product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plans
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlans()
|
||||
{
|
||||
// Get stripe plans
|
||||
$stripe_plans = $this->stripe->plans()->all();
|
||||
|
||||
// Plans container
|
||||
$plans = [];
|
||||
|
||||
foreach ($stripe_plans['data'] as $plan) {
|
||||
|
||||
// Get stripe product
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
// Push data to $plan container
|
||||
array_push($plans, [
|
||||
'plan' => $plan,
|
||||
'product' => $product,
|
||||
]);
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active plans
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActivePlans()
|
||||
{
|
||||
// Get stripe plans
|
||||
$stripe_plans = $this->stripe->plans()->all();
|
||||
|
||||
// Plans container
|
||||
$plans = [];
|
||||
|
||||
foreach ($stripe_plans['data'] as $plan) {
|
||||
|
||||
if ($plan['active']) {
|
||||
|
||||
// Get stripe product
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
// Push data to $plan container
|
||||
array_push($plans, [
|
||||
'plan' => $plan,
|
||||
'product' => $product,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete plan
|
||||
*
|
||||
* @param $slug
|
||||
*/
|
||||
public function deletePlan($slug)
|
||||
{
|
||||
$this->stripe->plans()->delete($slug);
|
||||
}
|
||||
}
|
||||
87
app/User.php
@@ -10,6 +10,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Laravel\Cashier\Billable;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use Rinvex\Subscriptions\Traits\HasSubscriptions;
|
||||
|
||||
@@ -53,10 +54,31 @@ use Rinvex\Subscriptions\Traits\HasSubscriptions;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRememberToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereUpdatedAt($value)
|
||||
* @mixin \Eloquent
|
||||
* @property string $role
|
||||
* @property string|null $stripe_id
|
||||
* @property string|null $card_brand
|
||||
* @property string|null $card_last_four
|
||||
* @property string|null $trial_ends_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $favourite_folders
|
||||
* @property-read int|null $favourite_folders_count
|
||||
* @property-read mixed $folder_tree
|
||||
* @property-read mixed $storage
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Invoice[] $invoices
|
||||
* @property-read int|null $invoices_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\UserCard[] $payment_cards
|
||||
* @property-read int|null $payment_cards_count
|
||||
* @property-read \App\UserSettings|null $settings
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Cashier\Subscription[] $subscriptions
|
||||
* @property-read int|null $subscriptions_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCardBrand($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCardLastFour($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRole($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereStripeId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereTrialEndsAt($value)
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens, Notifiable, HasSubscriptions;
|
||||
use HasApiTokens, Notifiable, Billable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -95,11 +117,11 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStorageAttribute() {
|
||||
|
||||
public function getStorageAttribute()
|
||||
{
|
||||
return [
|
||||
'used' => (float) get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity),
|
||||
'capacity' => $this->settings->storage_capacity,
|
||||
'used' => (float)get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity),
|
||||
'capacity' => $this->settings->storage_capacity,
|
||||
'capacity_formatted' => format_gigabytes($this->settings->storage_capacity),
|
||||
];
|
||||
}
|
||||
@@ -109,8 +131,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUsedCapacityAttribute() {
|
||||
|
||||
public function getUsedCapacityAttribute()
|
||||
{
|
||||
$user_capacity = $this->files_with_trashed->map(function ($item) {
|
||||
return $item->getRawOriginal();
|
||||
})->sum('filesize');
|
||||
@@ -118,7 +140,8 @@ class User extends Authenticatable
|
||||
return $user_capacity;
|
||||
}
|
||||
|
||||
public function getFolderTreeAttribute() {
|
||||
public function getFolderTreeAttribute()
|
||||
{
|
||||
return FileManagerFolder::with(['folders.shared', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('parent_id', 0)
|
||||
->where('user_id', $this->id)
|
||||
@@ -139,6 +162,24 @@ class User extends Authenticatable
|
||||
return url('/assets/images/' . 'default-avatar.png');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user billing info
|
||||
*
|
||||
* @param $billing
|
||||
*/
|
||||
public function setBilling($billing)
|
||||
{
|
||||
$this->settings()->update([
|
||||
'billing_address' => $billing['billing_address'],
|
||||
'billing_city' => $billing['billing_city'],
|
||||
'billing_country' => $billing['billing_country'],
|
||||
'billing_name' => $billing['billing_name'],
|
||||
'billing_phone_number' => $billing['billing_phone_number'],
|
||||
'billing_postal_code' => $billing['billing_postal_code'],
|
||||
'billing_state' => $billing['billing_state'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the password reset notification.
|
||||
*
|
||||
@@ -165,8 +206,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany|\Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function latest_uploads() {
|
||||
|
||||
public function latest_uploads()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class)->with(['parent'])->orderBy('created_at', 'DESC')->take(40);
|
||||
}
|
||||
|
||||
@@ -175,8 +216,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files() {
|
||||
|
||||
public function files()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class);
|
||||
}
|
||||
|
||||
@@ -185,8 +226,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files_with_trashed() {
|
||||
|
||||
public function files_with_trashed()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class)->withTrashed();
|
||||
}
|
||||
|
||||
@@ -195,8 +236,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function settings() {
|
||||
|
||||
public function settings()
|
||||
{
|
||||
return $this->hasOne(UserSettings::class);
|
||||
}
|
||||
|
||||
@@ -205,8 +246,18 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function invoices() {
|
||||
|
||||
public function invoices()
|
||||
{
|
||||
return $this->hasMany(Invoice::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user payment cards
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function payment_cards()
|
||||
{
|
||||
return $this->hasMany(UserCard::class);
|
||||
}
|
||||
}
|
||||
|
||||
48
app/UserCard.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\UserCard
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property string $provider
|
||||
* @property int $default
|
||||
* @property string $status
|
||||
* @property string $card_id
|
||||
* @property string $brand
|
||||
* @property string $last4
|
||||
* @property string $exp_month
|
||||
* @property string $exp_year
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\User|null $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereBrand($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereCardId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereDefault($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereExpMonth($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereExpYear($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereLast4($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereProvider($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereStatus($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\UserCard whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class UserCard extends Model
|
||||
{
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public function user() {
|
||||
|
||||
return $this->hasOne(User::class);
|
||||
}
|
||||
}
|
||||
@@ -9,18 +9,19 @@
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"cartalyst/stripe-laravel": "^12.0",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"fruitcake/laravel-cors": "^1.0",
|
||||
"gabrielelana/byte-units": "^0.5.0",
|
||||
"intervention/image": "^2.5",
|
||||
"laravel/cashier": "^12.0",
|
||||
"laravel/framework": "^7.0",
|
||||
"laravel/passport": "^8.4",
|
||||
"laravel/scout": "^7.2",
|
||||
"laravel/tinker": "^2.0",
|
||||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"rinvex/laravel-subscriptions": "^4.0",
|
||||
"teamtnt/laravel-scout-tntsearch-driver": "^8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -50,7 +51,8 @@
|
||||
"database/factories"
|
||||
],
|
||||
"files": [
|
||||
"app/Http/helpers.php"
|
||||
"app/Http//Helpers/helpers.php",
|
||||
"app/Http//Helpers/subscription.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
||||
692
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "32b62c653a002d0eea89b606c0f5982a",
|
||||
"content-hash": "e30e23b1a0df4073ff74004cde20ddb8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
@@ -188,6 +188,122 @@
|
||||
],
|
||||
"time": "2020-04-15T15:59:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "cartalyst/stripe",
|
||||
"version": "v2.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cartalyst/stripe.git",
|
||||
"reference": "f7753a8c947aa7c58abad96db8714e1594160b0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/cartalyst/stripe/zipball/f7753a8c947aa7c58abad96db8714e1594160b0c",
|
||||
"reference": "f7753a8c947aa7c58abad96db8714e1594160b0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9",
|
||||
"phpunit/phpunit": "~4.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"component": "package",
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Cartalyst\\Stripe\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cartalyst LLC",
|
||||
"email": "help@cartalyst.com",
|
||||
"homepage": "https://cartalyst.com"
|
||||
}
|
||||
],
|
||||
"description": "A comprehensive Stripe API package.",
|
||||
"keywords": [
|
||||
"cartalyst",
|
||||
"php",
|
||||
"stripe"
|
||||
],
|
||||
"time": "2020-01-03T12:02:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "cartalyst/stripe-laravel",
|
||||
"version": "v12.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cartalyst/stripe-laravel.git",
|
||||
"reference": "e171e6721e3491daa7eaa8d85ca6d4536086c327"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/cartalyst/stripe-laravel/zipball/e171e6721e3491daa7eaa8d85ca6d4536086c327",
|
||||
"reference": "e171e6721e3491daa7eaa8d85ca6d4536086c327",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"cartalyst/stripe": "^2.0",
|
||||
"illuminate/support": "^7.0",
|
||||
"php": "^7.2.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"cartalyst/php-cs-fixer-config": "^1.0",
|
||||
"phpunit/phpunit": "^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"component": "implementation",
|
||||
"branch-alias": {
|
||||
"dev-master": "12.0.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Cartalyst\\Stripe\\Laravel\\StripeServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Stripe": "Cartalyst\\Stripe\\Laravel\\Facades\\Stripe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Cartalyst\\Stripe\\Laravel\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cartalyst LLC",
|
||||
"email": "help@cartalyst.com",
|
||||
"homepage": "https://cartalyst.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel 7 integration for the Cartalyst Stripe package.",
|
||||
"keywords": [
|
||||
"cartalyst",
|
||||
"laravel",
|
||||
"php",
|
||||
"stripe"
|
||||
],
|
||||
"time": "2020-03-03T18:50:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "defuse/php-encryption",
|
||||
"version": "v2.2.1",
|
||||
@@ -675,6 +791,72 @@
|
||||
],
|
||||
"time": "2020-05-25T17:44:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dompdf/dompdf",
|
||||
"version": "v0.8.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/dompdf.git",
|
||||
"reference": "6782abfc090b132134cd6cea0ec6d76f0fce2c56"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/6782abfc090b132134cd6cea0ec6d76f0fce2c56",
|
||||
"reference": "6782abfc090b132134cd6cea0ec6d76f0fce2c56",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-mbstring": "*",
|
||||
"phenx/php-font-lib": "^0.5.1",
|
||||
"phenx/php-svg-lib": "^0.3.3",
|
||||
"php": "^7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "Needed to process images",
|
||||
"ext-gmagick": "Improves image processing performance",
|
||||
"ext-imagick": "Improves image processing performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "0.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dompdf\\": "src/"
|
||||
},
|
||||
"classmap": [
|
||||
"lib/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Brian Sweeney",
|
||||
"email": "eclecticgeek@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Gabriel Bull",
|
||||
"email": "me@gabrielbull.com"
|
||||
}
|
||||
],
|
||||
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||
"homepage": "https://github.com/dompdf/dompdf",
|
||||
"time": "2020-02-20T03:52:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
"version": "v2.3.0",
|
||||
@@ -1462,6 +1644,80 @@
|
||||
],
|
||||
"time": "2020-05-20T16:45:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/cashier",
|
||||
"version": "v12.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/cashier.git",
|
||||
"reference": "e3479f548a7d167ff1c241e718041162e66306a5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/cashier/zipball/e3479f548a7d167ff1c241e718041162e66306a5",
|
||||
"reference": "e3479f548a7d167ff1c241e718041162e66306a5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dompdf/dompdf": "^0.8.0",
|
||||
"ext-json": "*",
|
||||
"illuminate/contracts": "^6.0|^7.0",
|
||||
"illuminate/database": "^6.0|^7.0",
|
||||
"illuminate/http": "^6.0|^7.0",
|
||||
"illuminate/log": "^6.0|^7.0",
|
||||
"illuminate/notifications": "^6.0|^7.0",
|
||||
"illuminate/routing": "^6.0|^7.0",
|
||||
"illuminate/support": "^6.0|^7.0",
|
||||
"illuminate/view": "^6.0|^7.0",
|
||||
"moneyphp/money": "^3.2",
|
||||
"nesbot/carbon": "^2.0",
|
||||
"php": "^7.2",
|
||||
"stripe/stripe-php": "^7.0",
|
||||
"symfony/http-kernel": "^4.3|^5.0",
|
||||
"symfony/intl": "^4.3|^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.0",
|
||||
"orchestra/testbench": "^4.0|^5.0",
|
||||
"phpunit/phpunit": "^8.0|^9.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "Allows for more locales besides the default \"en\" when formatting money values."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "12.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Cashier\\CashierServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Cashier\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylorotwell@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.",
|
||||
"keywords": [
|
||||
"billing",
|
||||
"laravel",
|
||||
"stripe"
|
||||
],
|
||||
"time": "2020-06-16T18:54:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v7.14.1",
|
||||
@@ -2254,6 +2510,88 @@
|
||||
],
|
||||
"time": "2020-04-29T22:14:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "moneyphp/money",
|
||||
"version": "v3.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/moneyphp/money.git",
|
||||
"reference": "122664c2621a95180a13c1ac81fea1d2ef20781e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/moneyphp/money/zipball/122664c2621a95180a13c1ac81fea1d2ef20781e",
|
||||
"reference": "122664c2621a95180a13c1ac81fea1d2ef20781e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"cache/taggable-cache": "^0.4.0",
|
||||
"doctrine/instantiator": "^1.0.5",
|
||||
"ext-bcmath": "*",
|
||||
"ext-gmp": "*",
|
||||
"ext-intl": "*",
|
||||
"florianv/exchanger": "^1.0",
|
||||
"florianv/swap": "^3.0",
|
||||
"friends-of-phpspec/phpspec-code-coverage": "^3.1.1 || ^4.3",
|
||||
"moneyphp/iso-currencies": "^3.2.1",
|
||||
"php-http/message": "^1.4",
|
||||
"php-http/mock-client": "^1.0.0",
|
||||
"phpspec/phpspec": "^3.4.3",
|
||||
"phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.18 || ^8.5",
|
||||
"psr/cache": "^1.0",
|
||||
"symfony/phpunit-bridge": "^4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Calculate without integer limits",
|
||||
"ext-gmp": "Calculate without integer limits",
|
||||
"ext-intl": "Format Money objects with intl",
|
||||
"florianv/exchanger": "Exchange rates library for PHP",
|
||||
"florianv/swap": "Exchange rates library for PHP",
|
||||
"psr/cache-implementation": "Used for Currency caching"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Money\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mathias Verraes",
|
||||
"email": "mathias@verraes.net",
|
||||
"homepage": "http://verraes.net"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Frederik Bosch",
|
||||
"email": "f.bosch@genkgo.nl"
|
||||
}
|
||||
],
|
||||
"description": "PHP implementation of Fowler's Money pattern",
|
||||
"homepage": "http://moneyphp.org",
|
||||
"keywords": [
|
||||
"Value Object",
|
||||
"money",
|
||||
"vo"
|
||||
],
|
||||
"time": "2020-03-18T17:49:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "2.1.0",
|
||||
@@ -2686,6 +3024,83 @@
|
||||
],
|
||||
"time": "2018-07-02T15:55:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-font-lib",
|
||||
"version": "0.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PhenX/php-font-lib.git",
|
||||
"reference": "ca6ad461f032145fff5971b5985e5af9e7fa88d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/ca6ad461f032145fff5971b5985e5af9e7fa88d8",
|
||||
"reference": "ca6ad461f032145fff5971b5985e5af9e7fa88d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5 || ^6 || ^7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FontLib\\": "src/FontLib"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||
"homepage": "https://github.com/PhenX/php-font-lib",
|
||||
"time": "2020-03-08T15:31:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-svg-lib",
|
||||
"version": "v0.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PhenX/php-svg-lib.git",
|
||||
"reference": "5fa61b65e612ce1ae15f69b3d223cb14ecc60e32"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/5fa61b65e612ce1ae15f69b3d223cb14ecc60e32",
|
||||
"reference": "5fa61b65e612ce1ae15f69b3d223cb14ecc60e32",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"sabberworm/php-css-parser": "^8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.5|^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Svg\\": "src/Svg"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse and export to PDF SVG files.",
|
||||
"homepage": "https://github.com/PhenX/php-svg-lib",
|
||||
"time": "2019-09-11T20:02:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-http/message-factory",
|
||||
"version": "v1.0.2",
|
||||
@@ -3546,16 +3961,16 @@
|
||||
},
|
||||
{
|
||||
"name": "rinvex/laravel-subscriptions",
|
||||
"version": "v4.0.6",
|
||||
"version": "dev-subscription-query-fix",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rinvex/laravel-subscriptions.git",
|
||||
"reference": "f54539dfc98dbfa54d59e28c563e981fd28ad1f0"
|
||||
"url": "https://github.com/MakingCG/laravel-subscriptions.git",
|
||||
"reference": "0ed71077f34b9ca21c3755fcf09463b37802c0e8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rinvex/laravel-subscriptions/zipball/f54539dfc98dbfa54d59e28c563e981fd28ad1f0",
|
||||
"reference": "f54539dfc98dbfa54d59e28c563e981fd28ad1f0",
|
||||
"url": "https://api.github.com/repos/MakingCG/laravel-subscriptions/zipball/0ed71077f34b9ca21c3755fcf09463b37802c0e8",
|
||||
"reference": "0ed71077f34b9ca21c3755fcf09463b37802c0e8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3590,20 +4005,29 @@
|
||||
"Rinvex\\Subscriptions\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Rinvex\\Subscriptions\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": [
|
||||
"vendor/bin/phpunit"
|
||||
]
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rinvex LLC",
|
||||
"email": "help@rinvex.com",
|
||||
"homepage": "https://rinvex.com"
|
||||
"homepage": "https://rinvex.com",
|
||||
"email": "help@rinvex.com"
|
||||
},
|
||||
{
|
||||
"name": "Abdelrahman Omran",
|
||||
"email": "me@omranic.com",
|
||||
"homepage": "https://omranic.com",
|
||||
"email": "me@omranic.com",
|
||||
"role": "Project Lead"
|
||||
},
|
||||
{
|
||||
@@ -3622,7 +4046,13 @@
|
||||
"subscription",
|
||||
"value"
|
||||
],
|
||||
"time": "2020-05-30T02:21:52+00:00"
|
||||
"support": {
|
||||
"email": "help@rinvex.com",
|
||||
"issues": "https://github.com/rinvex/laravel-subscriptions/issues",
|
||||
"source": "https://github.com/rinvex/laravel-subscriptions",
|
||||
"docs": "https://github.com/rinvex/laravel-subscriptions/blob/master/README.md"
|
||||
},
|
||||
"time": "2020-06-15T13:17:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rinvex/laravel-support",
|
||||
@@ -3707,6 +4137,51 @@
|
||||
],
|
||||
"time": "2020-05-30T02:22:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabberworm/php-css-parser",
|
||||
"version": "8.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabberworm/PHP-CSS-Parser.git",
|
||||
"reference": "d217848e1396ef962fb1997cf3e2421acba7f796"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/d217848e1396ef962fb1997cf3e2421acba7f796",
|
||||
"reference": "d217848e1396ef962fb1997cf3e2421acba7f796",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"codacy/coverage": "^1.4",
|
||||
"phpunit/phpunit": "~4.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Sabberworm\\CSS": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raphael Schweikert"
|
||||
}
|
||||
],
|
||||
"description": "Parser for CSS Files written in PHP",
|
||||
"homepage": "http://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||
"keywords": [
|
||||
"css",
|
||||
"parser",
|
||||
"stylesheet"
|
||||
],
|
||||
"time": "2020-06-01T09:10:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/eloquent-sortable",
|
||||
"version": "3.8.0",
|
||||
@@ -3934,6 +4409,63 @@
|
||||
],
|
||||
"time": "2020-04-30T10:01:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "stripe/stripe-php",
|
||||
"version": "v7.37.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/stripe/stripe-php.git",
|
||||
"reference": "e3e29131a131785c3d2f85556b0154e8170e9bba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/e3e29131a131785c3d2f85556b0154e8170e9bba",
|
||||
"reference": "e3e29131a131785c3d2f85556b0154e8170e9bba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.16.1",
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"squizlabs/php_codesniffer": "^3.3",
|
||||
"symfony/process": "~3.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Stripe\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Stripe and contributors",
|
||||
"homepage": "https://github.com/stripe/stripe-php/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Stripe PHP Library",
|
||||
"homepage": "https://stripe.com/",
|
||||
"keywords": [
|
||||
"api",
|
||||
"payment processing",
|
||||
"stripe"
|
||||
],
|
||||
"time": "2020-06-11T16:27:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
"version": "v6.2.3",
|
||||
@@ -4570,6 +5102,82 @@
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2020-05-31T06:14:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/intl",
|
||||
"version": "v5.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/intl.git",
|
||||
"reference": "b21d69ebb33adfcb7e6d8b0a0a8799db7090705b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/b21d69ebb33adfcb7e6d8b0a0a8799db7090705b",
|
||||
"reference": "b21d69ebb33adfcb7e6d8b0a0a8799db7090705b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/polyfill-intl-icu": "~1.0",
|
||||
"symfony/polyfill-php80": "^1.15"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/filesystem": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "to use the component with locales other than \"en\""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Intl\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
],
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Bernhard Schussek",
|
||||
"email": "bschussek@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Eriksen Costa",
|
||||
"email": "eriksen.costa@infranology.com.br"
|
||||
},
|
||||
{
|
||||
"name": "Igor Wiedler",
|
||||
"email": "igor@wiedler.ch"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "A PHP replacement layer for the C intl extension that includes additional data from the ICU library.",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"i18n",
|
||||
"icu",
|
||||
"internationalization",
|
||||
"intl",
|
||||
"l10n",
|
||||
"localization"
|
||||
],
|
||||
"time": "2020-05-30T20:35:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v5.1.0",
|
||||
@@ -4810,6 +5418,64 @@
|
||||
],
|
||||
"time": "2020-05-12T16:47:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-icu",
|
||||
"version": "v1.17.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-icu.git",
|
||||
"reference": "4ef3923e4a86e1b6ef72d42be59dbf7d33a685e3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/4ef3923e4a86e1b6ef72d42be59dbf7d33a685e3",
|
||||
"reference": "4ef3923e4a86e1b6ef72d42be59dbf7d33a685e3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"symfony/intl": "~2.3|~3.0|~4.0|~5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.17-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's ICU-related data and classes",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"icu",
|
||||
"intl",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2020-05-12T16:14:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.17.0",
|
||||
@@ -8661,7 +9327,9 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"rinvex/laravel-subscriptions": 20
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
||||
@@ -193,51 +193,50 @@ return [
|
||||
|
||||
'aliases' => [
|
||||
|
||||
'App' => Illuminate\Support\Facades\App::class,
|
||||
'Arr' => Illuminate\Support\Arr::class,
|
||||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
'Auth' => Illuminate\Support\Facades\Auth::class,
|
||||
'Blade' => Illuminate\Support\Facades\Blade::class,
|
||||
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
|
||||
'Bus' => Illuminate\Support\Facades\Bus::class,
|
||||
'Cache' => Illuminate\Support\Facades\Cache::class,
|
||||
'Config' => Illuminate\Support\Facades\Config::class,
|
||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
||||
'DB' => Illuminate\Support\Facades\DB::class,
|
||||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||
'Event' => Illuminate\Support\Facades\Event::class,
|
||||
'File' => Illuminate\Support\Facades\File::class,
|
||||
'Gate' => Illuminate\Support\Facades\Gate::class,
|
||||
'Hash' => Illuminate\Support\Facades\Hash::class,
|
||||
'Lang' => Illuminate\Support\Facades\Lang::class,
|
||||
'Log' => Illuminate\Support\Facades\Log::class,
|
||||
'Mail' => Illuminate\Support\Facades\Mail::class,
|
||||
'App' => Illuminate\Support\Facades\App::class,
|
||||
'Arr' => Illuminate\Support\Arr::class,
|
||||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
'Auth' => Illuminate\Support\Facades\Auth::class,
|
||||
'Blade' => Illuminate\Support\Facades\Blade::class,
|
||||
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
|
||||
'Bus' => Illuminate\Support\Facades\Bus::class,
|
||||
'Cache' => Illuminate\Support\Facades\Cache::class,
|
||||
'Config' => Illuminate\Support\Facades\Config::class,
|
||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
||||
'DB' => Illuminate\Support\Facades\DB::class,
|
||||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||
'Event' => Illuminate\Support\Facades\Event::class,
|
||||
'File' => Illuminate\Support\Facades\File::class,
|
||||
'Gate' => Illuminate\Support\Facades\Gate::class,
|
||||
'Hash' => Illuminate\Support\Facades\Hash::class,
|
||||
'Lang' => Illuminate\Support\Facades\Lang::class,
|
||||
'Log' => Illuminate\Support\Facades\Log::class,
|
||||
'Mail' => Illuminate\Support\Facades\Mail::class,
|
||||
'Notification' => Illuminate\Support\Facades\Notification::class,
|
||||
'Password' => Illuminate\Support\Facades\Password::class,
|
||||
'Queue' => Illuminate\Support\Facades\Queue::class,
|
||||
'Redirect' => Illuminate\Support\Facades\Redirect::class,
|
||||
'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
'Request' => Illuminate\Support\Facades\Request::class,
|
||||
'Response' => Illuminate\Support\Facades\Response::class,
|
||||
'Route' => Illuminate\Support\Facades\Route::class,
|
||||
'Schema' => Illuminate\Support\Facades\Schema::class,
|
||||
'Session' => Illuminate\Support\Facades\Session::class,
|
||||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Str' => Illuminate\Support\Str::class,
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
|
||||
'Image' => Intervention\Image\Facades\Image::class
|
||||
|
||||
'Password' => Illuminate\Support\Facades\Password::class,
|
||||
'Queue' => Illuminate\Support\Facades\Queue::class,
|
||||
'Redirect' => Illuminate\Support\Facades\Redirect::class,
|
||||
'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
'Request' => Illuminate\Support\Facades\Request::class,
|
||||
'Response' => Illuminate\Support\Facades\Response::class,
|
||||
'Route' => Illuminate\Support\Facades\Route::class,
|
||||
'Schema' => Illuminate\Support\Facades\Schema::class,
|
||||
'Session' => Illuminate\Support\Facades\Session::class,
|
||||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Str' => Illuminate\Support\Str::class,
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
'Image' => Intervention\Image\Facades\Image::class,
|
||||
'Stripe' => Cartalyst\Stripe\Laravel\Facades\Stripe::class,
|
||||
],
|
||||
|
||||
'deploy_secret' => env('APP_DEPLOY_SECRET'),
|
||||
'deploy_branch' => env('APP_DEPLOY_BRANCH'),
|
||||
|
||||
'debug_blacklist' => [
|
||||
'_ENV' => [
|
||||
'_ENV' => [
|
||||
'APP_KEY',
|
||||
'DB_PASSWORD',
|
||||
'REDIS_PASSWORD',
|
||||
@@ -262,7 +261,7 @@ return [
|
||||
'AWS_ACCESS_KEY_ID',
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
],
|
||||
'_POST' => [
|
||||
'_POST' => [
|
||||
'password',
|
||||
],
|
||||
],
|
||||
|
||||
@@ -34,5 +34,4 @@ return [
|
||||
'client_id' => env('PASSPORT_CLIENT_ID'),
|
||||
'client_secret' => env('PASSPORT_CLIENT_SECRET'),
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
12
database/factories/UserCardFactory.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||
|
||||
use App\UserCard;
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(UserCard::class, function (Faker $faker) {
|
||||
return [
|
||||
//
|
||||
];
|
||||
});
|
||||
@@ -26,7 +26,7 @@ class CreateFileManagerFiles extends Migration
|
||||
$table->text('mimetype')->nullable();
|
||||
$table->text('filesize')->nullable();
|
||||
|
||||
$table->enum('type', ['image', 'file'])->nullable();
|
||||
$table->text('type')->nullable();
|
||||
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ChangeTypeAttributeInFileManagerFilesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
DB::statement('ALTER TABLE file_manager_files MODIFY type TEXT;');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ class CreatePaymentGatewaysTable extends Migration
|
||||
$table->text('client_id')->nullable();
|
||||
$table->text('secret')->nullable();
|
||||
$table->text('webhook')->nullable();
|
||||
$table->bigInteger('payment_processed')->default(0);
|
||||
$table->longText('optional')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ class CreateInvoicesTable extends Migration
|
||||
$table->bigIncrements('id');
|
||||
$table->text('token');
|
||||
$table->text('order');
|
||||
$table->text('provider');
|
||||
$table->text('user_id');
|
||||
$table->text('plan_id');
|
||||
$table->longText('seller');
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateUserCardsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('user_cards', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->bigInteger('user_id');
|
||||
$table->text('provider');
|
||||
$table->text('card_id');
|
||||
$table->text('brand');
|
||||
$table->text('last4');
|
||||
$table->text('exp_month');
|
||||
$table->text('exp_year');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('user_cards');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddStatusToUserCardsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('user_cards', function (Blueprint $table) {
|
||||
$table->text('status')->after('provider');
|
||||
$table->boolean('default')->default(0)->after('provider');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('user_cards', function (Blueprint $table) {
|
||||
$table->removeColumn('status');
|
||||
$table->removeColumn('default');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreatePlansTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create(config('rinvex.subscriptions.tables.plans'), function (Blueprint $table) {
|
||||
// Columns
|
||||
$table->increments('id');
|
||||
$table->string('slug');
|
||||
$table->{$this->jsonable()}('name');
|
||||
$table->{$this->jsonable()}('description')->nullable();
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->decimal('price')->default('0.00');
|
||||
$table->decimal('signup_fee')->default('0.00');
|
||||
$table->string('currency', 3);
|
||||
$table->smallInteger('trial_period')->unsigned()->default(0);
|
||||
$table->string('trial_interval')->default('day');
|
||||
$table->smallInteger('invoice_period')->unsigned()->default(0);
|
||||
$table->string('invoice_interval')->default('month');
|
||||
$table->smallInteger('grace_period')->unsigned()->default(0);
|
||||
$table->string('grace_interval')->default('day');
|
||||
$table->tinyInteger('prorate_day')->unsigned()->nullable();
|
||||
$table->tinyInteger('prorate_period')->unsigned()->nullable();
|
||||
$table->tinyInteger('prorate_extend_due')->unsigned()->nullable();
|
||||
$table->smallInteger('active_subscribers_limit')->unsigned()->nullable();
|
||||
$table->mediumInteger('sort_order')->unsigned()->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Indexes
|
||||
$table->unique('slug');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists(config('rinvex.subscriptions.tables.plans'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jsonable column data type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function jsonable(): string
|
||||
{
|
||||
$driverName = DB::connection()->getPdo()->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
$dbVersion = DB::connection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
$isOldVersion = version_compare($dbVersion, '5.7.8', 'lt');
|
||||
|
||||
return $driverName === 'mysql' && $isOldVersion ? 'text' : 'json';
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreatePlanFeaturesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create(config('rinvex.subscriptions.tables.plan_features'), function (Blueprint $table) {
|
||||
// Columns
|
||||
$table->increments('id');
|
||||
$table->integer('plan_id')->unsigned();
|
||||
$table->string('slug');
|
||||
$table->{$this->jsonable()}('name');
|
||||
$table->{$this->jsonable()}('description')->nullable();
|
||||
$table->string('value');
|
||||
$table->smallInteger('resettable_period')->unsigned()->default(0);
|
||||
$table->string('resettable_interval')->default('month');
|
||||
$table->mediumInteger('sort_order')->unsigned()->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Indexes
|
||||
$table->unique(['plan_id', 'slug']);
|
||||
$table->foreign('plan_id')->references('id')->on(config('rinvex.subscriptions.tables.plans'))
|
||||
->onDelete('cascade')->onUpdate('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists(config('rinvex.subscriptions.tables.plan_features'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jsonable column data type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function jsonable(): string
|
||||
{
|
||||
$driverName = DB::connection()->getPdo()->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
$dbVersion = DB::connection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
$isOldVersion = version_compare($dbVersion, '5.7.8', 'lt');
|
||||
|
||||
return $driverName === 'mysql' && $isOldVersion ? 'text' : 'json';
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreatePlanSubscriptionsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create(config('rinvex.subscriptions.tables.plan_subscriptions'), function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->morphs('user');
|
||||
$table->integer('plan_id')->unsigned();
|
||||
$table->string('slug');
|
||||
$table->{$this->jsonable()}('name');
|
||||
$table->{$this->jsonable()}('description')->nullable();
|
||||
$table->dateTime('trial_ends_at')->nullable();
|
||||
$table->dateTime('starts_at')->nullable();
|
||||
$table->dateTime('ends_at')->nullable();
|
||||
$table->dateTime('cancels_at')->nullable();
|
||||
$table->dateTime('canceled_at')->nullable();
|
||||
$table->string('timezone')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Indexes
|
||||
$table->unique('slug');
|
||||
$table->foreign('plan_id')->references('id')->on(config('rinvex.subscriptions.tables.plans'))
|
||||
->onDelete('cascade')->onUpdate('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists(config('rinvex.subscriptions.tables.plan_subscriptions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jsonable column data type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function jsonable(): string
|
||||
{
|
||||
$driverName = DB::connection()->getPdo()->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
$dbVersion = DB::connection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
$isOldVersion = version_compare($dbVersion, '5.7.8', 'lt');
|
||||
|
||||
return $driverName === 'mysql' && $isOldVersion ? 'text' : 'json';
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreatePlanSubscriptionUsageTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create(config('rinvex.subscriptions.tables.plan_subscription_usage'), function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('subscription_id')->unsigned();
|
||||
$table->integer('feature_id')->unsigned();
|
||||
$table->smallInteger('used')->unsigned();
|
||||
$table->dateTime('valid_until')->nullable();
|
||||
$table->string('timezone')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->unique(['subscription_id', 'feature_id']);
|
||||
$table->foreign('subscription_id')->references('id')->on(config('rinvex.subscriptions.tables.plan_subscriptions'))
|
||||
->onDelete('cascade')->onUpdate('cascade');
|
||||
$table->foreign('feature_id')->references('id')->on(config('rinvex.subscriptions.tables.plan_features'))
|
||||
->onDelete('cascade')->onUpdate('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists(config('rinvex.subscriptions.tables.plan_subscription_usage'));
|
||||
}
|
||||
}
|
||||
1
public/assets/icons/alipay.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg width="780" height="500" enable-background="new 0 0 780 500" version="1.1" viewBox="0 0 780 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M40,0h700c22.092,0,40,17.909,40,40v420c0,22.092-17.908,40-40,40H40c-22.091,0-40-17.908-40-40V40 C0,17.909,17.909,0,40,0z" fill="#fff"/><path d="m114.26 257.95c-4.8 0.601-13.203 2.4-18.004 6.601-14.403 12.599-6.001 34.798 23.406 34.798 16.803 0 33.607-10.8 46.81-27.6-19.204-9-34.808-15.6-52.212-13.799z" fill="#2BA6DF"/><path d="m221.83 273.4c27.006 9 33.007 9.6 33.007 9.6v-95.998c0-16.199-13.203-29.398-30.006-29.398h-126.03c-16.204 0-30.007 13.2-30.007 29.4v126c0 16.199 13.203 29.398 30.007 29.398h126.03c16.203 0 30.006-13.2 30.006-29.4v-1.199s-48.01-19.799-72.616-31.799c-16.203 19.799-37.208 32.399-59.413 32.399-37.208 0-49.811-32.399-31.807-53.399 3.6-4.8 10.202-9 20.404-11.399 15.604-3.601 40.81 2.399 64.215 10.2 4.2-7.801 7.801-16.2 10.202-25.2h-72.616v-7.2h37.208v-14.399h-45.61v-7.2h45.61v-18.599s0-3 3-3h18.005v22.2h45.01v6.601h-45.01v13.199h36.608c-3.6 14.399-9.002 27.599-15.604 38.998 12.003 4.2 22.205 7.801 29.407 10.199z" fill="#2BA6DF"/><path d="m340.49 201.22l39.608 85.797h-21.005l-10.802-22.801h-32.408l-10.802 22.801h-13.803l40.209-83.398s1.199-2.4 3.6-2.4h5.402v1e-3zm-21.006 55.197h25.206l-12.603-27-12.603 27zm87.448 31.282h-19.204v-81.598c0-2.399 1.2-3.601 4.2-3.601h15.004v85.199zm36.007-0.558h-19.203v-61.798c0-2.4 1.199-3.601 4.199-3.601h15.004v65.399zm23.483-64.116h12.604v6c2.4-1.8 4.801-3.601 7.801-4.2 3.002-1.199 6.002-1.8 10.203-1.8 4.199 0 7.801 0.601 10.803 2.399 3.6 1.801 6 3.601 8.4 6.601s4.201 6 5.402 9.601c1.199 3.6 1.799 7.199 1.799 11.398 0 5.4-0.6 10.2-2.398 14.4-1.801 4.199-3.602 8.399-6.602 11.399-3.002 3-6.002 5.999-10.203 7.8-4.201 1.799-8.402 2.399-13.203 2.399h-6.602c-1.799 0-3.6-0.601-5.4-1.2v21.6h-19.206v-78.598c-0.599-7.799 2.401-7.799 6.602-7.799zm12.603 46.798c0 1.801 0 3 0.6 4.2s1.201 2.399 2.4 3.601c1.199 1.199 2.4 1.799 3.602 2.399 1.199 0.601 3 0.601 4.801 0.601 1.799 0 3-0.601 4.801-1.801 1.199-1.199 3-2.4 3.602-4.8 0.6-2.399 1.799-4.2 2.398-7.2 0.602-3 1.201-5.4 1.201-9 0-4.199 0-7.799-0.6-10.799-0.602-3-1.201-5.4-2.4-7.8-1.201-1.8-2.4-3.601-3.6-4.8-1.201-1.2-3.002-1.801-4.803-1.801-1.199 0-2.4 0-3.6 0.601-1.201 0.601-2.4 1.2-3.002 1.8-1.199 0.6-1.799 1.801-3 2.4-1.201 1.199-1.801 1.8-2.4 3v29.4-1e-3zm81.028-46.798c4.801 0 8.402 0.601 12.002 1.2 3 0.6 6.002 1.8 8.402 3.6 2.4 1.801 3.6 3.6 4.801 5.4 1.199 2.4 1.801 4.8 1.801 7.199v47.398h-19.205v-4.8c-1.199 1.2-2.398 1.8-3 2.399l-3.602 1.801c-1.199 0.6-2.4 1.199-4.199 1.199-1.801 0.601-3.602 0.601-5.402 0.601-3 0-5.4-0.601-7.803-1.2-2.398-0.6-4.199-1.8-6-3.6-1.801-1.2-3.002-3-3.602-5.4-0.6-1.8-1.199-4.199-1.199-6.6s0.6-4.801 1.199-6.6c0.6-1.801 2.4-3.601 3.602-5.4 1.199-1.801 3.6-3 5.4-4.2 2.4-1.2 4.201-2.399 7.203-3.601 2.398-1.198 4.799-1.799 7.801-2.998 2.4-0.601 5.4-1.801 7.801-2.4l2.4-0.6v-6.601c0-1.8 0-3.6-0.6-5.399l-1.801-3.601c-0.6-0.6-1.799-1.8-2.398-1.8-1.201-0.6-2.4-0.6-3.602-0.6 0 0-10.203 0-19.205 7.8l-4.201-6.601c-1.798 1.203 9.004-6.596 23.407-6.596zm6.599 31.799c-1.799 0.601-3.6 1.8-5.398 3l-5.402 3.601c-1.801 1.199-3 2.399-3.6 4.199-1.201 1.2-1.201 3-1.201 4.2s0 2.4 0.6 3.601c0.6 1.199 0.6 1.8 1.199 3 0.602 1.199 1.201 1.199 1.801 1.8 0.6 0.6 1.201 0.6 2.4 0.6 1.801 0 3.002-0.6 4.801-1.2l5.402-3.6v-19.2h-0.602zm46.555 53.998h-12.604l-0.6-11.399s15.604 0.6 20.404-5.4c1.801-2.4 3-8.999 3-8.999l-31.205-59.998h21.004l19.805 38.999 17.404-39h13.803l-31.807 70.799c-1.2 2.4-6.001 14.999-19.204 14.998z" fill="#3F3A39"/><ellipse cx="433.4" cy="204.1" rx="9.602" ry="8.5" fill="#2BA6DF"/><path d="m683.68 172.91h-6.602v-1.201h14.402v1.201h-6.6v18.599h-1.801v-18.599h0.601zm10.716-1.201h2.4l4.201 11.4 1.801 4.2c0.6-1.2 1.199-3 1.799-4.2l4.201-11.4h2.4v20.4h-2.398v-18l-1.8 4.801-4.201 12h-1.199l-4.201-12-1.801-4.801v18h-1.801v-20.4h0.599z" fill="#3F3A39"/></svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
1
public/assets/icons/amex.svg
Executable file
|
After Width: | Height: | Size: 4.9 KiB |
1
public/assets/icons/code.svg
Executable file
|
After Width: | Height: | Size: 12 KiB |
1
public/assets/icons/diners.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg width="780" height="500" enable-background="new 0 0 780 500" version="1.1" viewBox="0 0 780 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M40,0h700c22.092,0,40,17.909,40,40v420c0,22.092-17.908,40-40,40H40c-22.091,0-40-17.908-40-40V40 C0,17.909,17.909,0,40,0z" fill="#0079BE"/><path d="m599.93 251.45c0-99.415-82.98-168.13-173.9-168.1h-78.242c-92.003-0.033-167.73 68.705-167.73 168.1 0 90.93 75.727 165.64 167.73 165.2h78.242c90.914 0.436 173.9-74.294 173.9-165.2z" fill="#fff"/><path d="m348.28 97.43c-84.07 0.027-152.19 68.308-152.21 152.58 0.02 84.258 68.144 152.53 152.21 152.56 84.09-0.027 152.23-68.303 152.24-152.56-0.011-84.272-68.149-152.55-152.24-152.58z" fill="#0079BE"/><path d="m252.07 249.6c0.08-41.181 25.746-76.297 61.94-90.25v180.48c-36.194-13.948-61.861-49.045-61.94-90.23zm131 90.274v-180.53c36.207 13.92 61.914 49.057 61.979 90.257-0.065 41.212-25.772 76.322-61.979 90.269z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 945 B |
1
public/assets/icons/discover.svg
Executable file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="780" height="500" viewBox="0 0 780 500" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M54.992 0C24.627 0 0 24.63 0 55.004v390.992C0 476.376 24.619 501 54.992 501h670.016C755.373 501 780 476.37 780 445.996V55.004C780 24.624 755.381 0 725.008 0H54.992z" fill="#4D4D4D"/><path d="M327.152 161.893c8.837 0 16.248 1.784 25.268 6.09v22.751c-8.544-7.863-15.955-11.154-25.756-11.154-19.264 0-34.414 15.015-34.414 34.05 0 20.075 14.681 34.196 35.37 34.196 9.312 0 16.586-3.12 24.8-10.857v22.763c-9.341 4.14-16.911 5.776-25.756 5.776-31.278 0-55.582-22.596-55.582-51.737 0-28.826 24.951-51.878 56.07-51.878zm-97.113.627c11.546 0 22.11 3.72 30.943 10.994l-10.748 13.248c-5.35-5.646-10.41-8.028-16.564-8.028-8.853 0-15.3 4.745-15.3 10.989 0 5.354 3.619 8.188 15.944 12.482 23.365 8.044 30.29 15.176 30.29 30.926 0 19.193-14.976 32.553-36.32 32.553-15.63 0-26.994-5.795-36.458-18.872l13.268-12.03c4.73 8.61 12.622 13.222 22.42 13.222 9.163 0 15.947-5.952 15.947-13.984 0-4.164-2.055-7.734-6.158-10.258-2.066-1.195-6.158-2.977-14.2-5.647-19.291-6.538-25.91-13.527-25.91-27.185 0-16.225 14.214-28.41 32.846-28.41zm234.723 1.728h22.437l28.084 66.592 28.446-66.592h22.267l-45.494 101.686h-11.053l-44.687-101.686zm-397.348.152h30.15c33.312 0 56.534 20.382 56.534 49.641 0 14.59-7.104 28.696-19.118 38.057-10.108 7.901-21.626 11.445-37.574 11.445H67.414V164.4zm96.135 0h20.54v99.143h-20.54V164.4zm411.734 0h58.252v16.8H595.81v22.005h36.336v16.791h-36.336v26.762h37.726v16.785h-58.252V164.4zm71.858 0h30.455c23.69 0 37.265 10.71 37.265 29.272 0 15.18-8.514 25.14-23.986 28.105l33.148 41.766h-25.26l-28.429-39.828h-2.678v39.828h-20.515V164.4zm20.515 15.616v30.025h6.002c13.117 0 20.069-5.362 20.069-15.328 0-9.648-6.954-14.697-19.745-14.697h-6.326zM87.94 181.199v65.559h5.512c13.273 0 21.656-2.394 28.11-7.88 7.103-5.955 11.376-15.465 11.376-24.98 0-9.499-4.273-18.725-11.376-24.681-6.785-5.78-14.837-8.018-28.11-8.018H87.94z" fill="#FFF"/><path d="m415.13 161.21c30.941 0 56.022 23.58 56.022 52.709v0.033c0 29.13-25.081 52.742-56.021 52.742s-56.022-23.613-56.022-52.742v-0.033c0-29.13 25.082-52.71 56.022-52.71zm364.85 127.15c-26.05 18.33-221.08 149.34-558.75 212.62h503.76c30.365 0 54.992-24.63 54.992-55.004v-157.62z" fill="#F47216"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
public/assets/icons/elo.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg width="780" height="500" enable-background="new 0 0 780 500" version="1.1" viewBox="0 0 780 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M41.68,0h698.14c23.027,0,41.68,18.983,41.68,42.42v414.66c0,23.437-18.652,42.42-41.68,42.42H41.68 C18.652,499.5,0,480.517,0,457.08V42.42C0,18.983,18.652,0,41.68,0z"/><path d="m167.25 181.4c6.8-2.3 14.1-3.5 21.7-3.5 33.2 0 60.9 23.601 67.2 54.9l47-9.6c-10.8-53.2-57.8-93.301-114.2-93.301-12.9 0-25.3 2.101-36.9 6l15.2 45.501z" fill="#FFF100"/><path d="m111.75 333.8l31.8-36c-14.2-12.6-23.1-30.9-23.1-51.4 0-20.399 8.9-38.8 23.1-51.3l-31.8-35.899c-24.1 21.399-39.3 52.5-39.3 87.3 0 34.699 15.2 65.898 39.3 87.299z" fill="#00A3DF"/><path d="m256.15 260.2c-6.4 31.3-34 54.8-67.2 54.8-7.6 0-14.9-1.2-21.8-3.5l-15.2 45.5c11.6 3.899 24.1 6 37 6 56.4 0 103.4-40 114.2-93.2l-47-9.6z" fill="#EE4023"/><path d="m459.75 292.4c-7.8 7.601-18.3 12.2-29.9 12-8-0.1-15.399-2.5-21.6-6.5l-15.601 24.801c10.7 6.699 23.2 10.699 36.801 10.899 19.699 0.3 37.699-7.5 50.8-20.2l-20.5-21zm-28.2-101.1c-39.2-0.6-71.6 30.8-72.2 70-0.2 14.7 4 28.5 11.5 39.9l128.8-55.101c-7.2-30.899-34.8-54.2-68.1-54.799m-42.7 75.599c-0.2-1.6-0.3-3.3-0.3-5 0.4-23.1 19.4-41.6 42.5-41.199 12.6 0.199 23.8 5.899 31.3 14.899l-73.5 31.3zm151.3-107.6v137.3l23.801 9.9-11.301 27.1-23.6-9.8c-5.3-2.3-8.9-5.8-11.6-9.8-2.601-4-4.601-9.601-4.601-17v-137.7h27.301zm85.901 63.5c4.2-1.4 8.6-2.1 13.3-2.1 20.3 0 37.101 14.399 41 33.5l28.7-5.9c-6.6-32.5-35.3-56.9-69.7-56.9-7.899 0-15.5 1.301-22.5 3.601l9.2 27.799zm-33.901 92.9l19.4-21.9c-8.7-7.7-14.1-18.9-14.1-31.4s5.5-23.699 14.1-31.3l-19.4-21.899c-14.699 13-24 32.1-24 53.3s9.301 40.199 24 53.199zm88.201-44.801c-3.899 19.101-20.8 33.5-41 33.5-4.6 0-9.1-0.8-13.3-2.199l-9.3 27.8c7.1 2.399 14.7 3.7 22.6 3.7 34.4 0 63.101-24.4 69.7-56.9l-28.7-5.901z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
public/assets/icons/generic.svg
Executable file
|
After Width: | Height: | Size: 11 KiB |
28
public/assets/icons/hiper.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 780 500" style="enable-background:new 0 0 780 500;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F37421;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#FFE700;}
|
||||
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M724.3,0H55.7C25.4,0,0.8,24.6,0.8,54.9v390.2c0,30.3,24.6,54.9,54.9,54.9h668.7c30.3,0,54.9-24.6,54.9-54.9
|
||||
V54.9C779.2,24.6,754.6,0,724.3,0z"/>
|
||||
<g>
|
||||
<polygon class="st1" points="100,139.9 100,314.9 139.7,314.9 139.7,241.7 204.9,241.7 204.9,314.9 244.4,314.9 244.4,139.9
|
||||
204.9,139.9 204.9,207.2 139.7,207.2 139.7,139.9 100,139.9 "/>
|
||||
<path class="st1" d="M586.2,264c0.5-2.9,1.3-8.8,1.3-15.6c0-31.4-15.6-63.4-56.6-63.4c-44.1,0-64.1,35.6-64.1,67.8
|
||||
c0,39.7,24.7,64.7,67.8,64.7c17.1,0,33-2.6,46-7.8l-5.2-26.7c-10.6,3.4-21.6,5.2-35.1,5.2c-18.4,0-34.5-7.8-35.8-24.1H586.2
|
||||
L586.2,264z M504.1,237c1-10.6,7.8-25.7,24.4-25.7c18.2,0,22.3,16.1,22.3,25.7H504.1L504.1,237z"/>
|
||||
<path class="st1" d="M600.1,314.9h39.5v-64.4c0-3.1,0.3-6.2,0.8-8.8c2.6-12.2,12.5-20,27-20c4.4,0,7.8,0.5,10.6,1v-37.1
|
||||
c-2.9-0.5-4.7-0.5-8.3-0.5c-12.2,0-27.8,7.8-34.3,26.2h-1l-1.3-23.4h-34c0.5,10.9,1,23.1,1,41.8V314.9L600.1,314.9z"/>
|
||||
<path class="st2" d="M284.5,132.9c11.2,0,20.3,9.1,20.3,20.3c0,11.2-9.1,20.3-20.3,20.3c-11.2,0-20.3-9.1-20.3-20.3
|
||||
C264.2,142,273.3,132.9,284.5,132.9L284.5,132.9z"/>
|
||||
<path class="st3" d="M367.9,285.3h19.8c19.9,0,28.9-12.7,28.9-26c0-13.3-1-43.3-25.5-43.3c-28.2,0-23.7,37.3-23.5,56.8
|
||||
C367.5,277,367.8,281.2,367.9,285.3L367.9,285.3z M264.2,187.8h40.6v71.6c0,13.3,7.4,26,23.7,26c0.1-32.2,0-65.4-1.1-97.6h33.9
|
||||
c0.7,6.2,1.4,12.4,2,18.6c16-32,66.5-25,83.5,2.1c17.5,27.9,23.5,107.9-59.1,107.9h-19.2c0.2,16.2,0.2,32.5,0.2,48.8h-40.6
|
||||
c0-15.6,0.1-32,0.2-48.8c-43.9-0.2-64.1-28-64.1-57V187.8L264.2,187.8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
public/assets/icons/hipercard.svg
Executable file
|
After Width: | Height: | Size: 17 KiB |
1
public/assets/icons/jcb.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg width="780" height="500" enable-background="new 0 0 780 500" version="1.1" viewBox="0 0 780 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M40,0h700c22.092,0,40,17.909,40,40v420c0,22.092-17.908,40-40,40H40c-22.091,0-40-17.908-40-40V40 C0,17.909,17.909,0,40,0z" fill="#0E4C96"/><path d="m632.24 361.27c0 41.615-33.729 75.36-75.36 75.36h-409.13v-297.88c0-41.626 33.733-75.37 75.365-75.37l409.12-1e-3 1e-3 297.89z" fill="#fff"/><linearGradient id="c" x1="83.977" x2="84.977" y1="645.5" y2="645.5" gradientTransform="matrix(132.87 0 0 -323.02 -10686 2.0876e5)" gradientUnits="userSpaceOnUse"><stop stop-color="#007B40" offset="0"/><stop stop-color="#55B330" offset="1"/></linearGradient><path d="m498.86 256.54c11.684 0.253 23.437-0.516 35.076 0.4 11.787 2.199 14.629 20.043 4.156 25.888-7.141 3.851-15.633 1.433-23.379 2.113h-15.852l-1e-3 -28.401zm41.833-32.145c2.596 9.164-6.238 17.392-15.066 16.13h-26.767c0.185-8.642-0.368-18.021 0.271-26.208 10.725 0.301 21.549-0.616 32.21 0.479 4.581 1.151 8.414 4.917 9.352 9.599zm64.428-135.9c0.498 17.501 0.071 35.927 0.214 53.783-0.035 72.596 0.072 145.19-0.055 217.79-0.47 27.207-24.582 50.844-51.601 51.387-27.046 0.111-54.095 0.016-81.142 0.047v-109.75c29.47-0.154 58.959 0.307 88.417-0.232 13.667-0.859 28.632-9.875 29.27-24.914 1.61-15.103-12.632-25.551-26.152-27.201-5.198-0.135-5.044-1.516 0-2.117 12.892-2.787 23.02-16.133 19.226-29.499-3.236-14.058-18.772-19.499-31.697-19.472-26.351-0.18-52.709-0.026-79.062-0.077 0.172-20.489-0.354-41 0.286-61.474 2.087-26.716 26.806-48.747 53.447-48.27h78.849v-1e-3z" fill="url(#c)"/><linearGradient id="b" x1="83.984" x2="84.979" y1="645.5" y2="645.5" gradientTransform="matrix(133.43 0 0 -323.02 -11031 2.0876e5)" gradientUnits="userSpaceOnUse"><stop stop-color="#1D2970" offset="0"/><stop stop-color="#006DBA" offset="1"/></linearGradient><path d="m174.74 139.54c0.674-27.163 24.889-50.611 51.875-51.007 26.944-0.083 53.891-0.012 80.837-0.036-0.074 90.885 0.148 181.78-0.112 272.66-1.038 26.835-24.99 49.835-51.679 50.308-26.996 0.099-53.995 0.014-80.992 0.042v-113.45c26.223 6.194 53.722 8.832 80.473 4.721 15.993-2.574 33.488-10.424 38.902-27.014 3.986-14.191 1.742-29.126 2.334-43.691v-33.824h-46.297c-0.208 22.369 0.426 44.779-0.335 67.125-1.248 13.734-14.846 22.46-27.8 21.994-16.066 0.17-47.898-11.639-47.898-11.639-0.08-41.918 0.466-94.409 0.692-136.18z" fill="url(#b)"/><linearGradient id="a" x1="83.978" x2="84.977" y1="645.5" y2="645.5" gradientTransform="matrix(132.96 0 0 -323.03 -10842 2.0877e5)" gradientUnits="userSpaceOnUse"><stop stop-color="#6E2B2F" offset="0"/><stop stop-color="#E30138" offset="1"/></linearGradient><path d="m324.72 211.89c-2.434 0.517-0.489-8.301-1.113-11.646 0.165-21.15-0.347-42.323 0.283-63.458 2.083-26.829 26.991-48.916 53.739-48.288h78.766c-0.073 90.884 0.147 181.78-0.111 272.66-1.039 26.834-24.992 49.833-51.681 50.308-26.997 0.1-53.997 0.015-80.997 0.043v-124.3c18.44 15.128 43.5 17.483 66.473 17.524 17.316-6e-3 34.534-2.674 51.35-6.67v-22.772c-18.953 9.446-41.232 15.446-62.243 10.019-14.655-3.65-25.294-17.812-25.056-32.937-1.699-15.728 7.524-32.335 22.981-37.011 19.189-6.008 40.107-1.413 58.096 6.397 3.854 2.019 7.765 4.521 6.222-1.921v-17.9c-30.084-7.156-62.101-9.792-92.329-2.004-8.749 2.469-17.271 6.212-24.38 11.958z" fill="url(#a)"/></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
1
public/assets/icons/maestro.svg
Executable file
|
After Width: | Height: | Size: 7.2 KiB |
1
public/assets/icons/mastercard.svg
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
32
public/assets/icons/mir.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 780 500" style="enable-background:new 0 0 780 500;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill:#37A72E;}
|
||||
.st2{fill:url(#Combined-Shape_4_);}
|
||||
</style>
|
||||
<path class="st0" d="M40,0h700c22.1,0,40,17.9,40,40v420c0,22.1-17.9,40-40,40H40c-22.1,0-40-17.9-40-40V40C0,17.9,17.9,0,40,0z"/>
|
||||
<g id="Page-1">
|
||||
<g id="Artboard" transform="translate(-91.000000, -154.000000)">
|
||||
<g id="Group" transform="translate(91.000000, 154.000000)">
|
||||
<path id="Combined-Shape" class="st1" d="M544.1,240.5v108h60v-64h68c28.6-0.2,52.9-18.5,62.1-44H544.1z"/>
|
||||
|
||||
<linearGradient id="Combined-Shape_4_" gradientUnits="userSpaceOnUse" x1="362.4047" y1="275.4307" x2="363.4047" y2="275.4307" gradientTransform="matrix(201.7633 0 0 -79 -72583.8438 21950.0254)">
|
||||
<stop offset="0" style="stop-color:#00A0E5"/>
|
||||
<stop offset="1" style="stop-color:#0077C3"/>
|
||||
</linearGradient>
|
||||
<path id="Combined-Shape_1_" class="st2" d="M536.1,151.5c3.5,44.1,45.3,79,96.3,79c0.2,0,104.3,0,104.3,0
|
||||
c0.8-4,1.2-8.2,1.2-12.5c0-36.6-29.5-66.2-66-66.5L536.1,151.5z"/>
|
||||
<path id="Combined-Shape_2_" class="st1" d="M447.3,229.4l0-0.1L447.3,229.4c0.7-1.2,1.8-1.9,3.2-1.9c2,0,3.5,1.6,3.6,3.5l0,0
|
||||
v116.5h60v-196h-60c-7.6,0.3-16.2,5.8-19.4,12.7L387,266.6c-0.1,0.4-0.3,0.8-0.5,1.2l0,0l0,0c-0.7,1-1.9,1.7-3.3,1.7
|
||||
c-2.2,0-4-1.8-4-4v-114h-60v196h60v0c7.5-0.4,15.9-5.9,19.1-12.7l49-105.1C447.2,229.6,447.3,229.5,447.3,229.4L447.3,229.4z"/>
|
||||
<path id="Combined-Shape_3_" class="st1" d="M223.3,232.8l-35.1,114.7H145L110,232.7c-0.3-1.8-1.9-3.2-3.9-3.2
|
||||
c-2.2,0-3.9,1.8-3.9,3.9c0,0,0,0,0,0l0,114h-60v-196h51.5H109c11,0,22.6,8.6,25.8,19.1l29.2,95.5c1.5,4.8,3.8,4.7,5.3,0
|
||||
l29.2-95.5c3.2-10.6,14.8-19.1,25.8-19.1h15.3h51.5v196h-60v-114c0,0,0,0,0-0.1c0-2.2-1.8-3.9-3.9-3.9
|
||||
C225.2,229.5,223.6,230.9,223.3,232.8L223.3,232.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
public/assets/icons/paypal.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg width="780" height="500" enable-background="new 0 0 780 500" version="1.1" viewBox="0 0 780 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M725,0H55C24.673,0,0,24.673,0,55v391c0,30.327,24.673,55,55,55h670c30.325,0,55-24.673,55-55V55 C780,24.673,755.325,0,725,0z" fill="#FFF"/><path d="m168.38 169.85c-8.399-5.774-19.359-8.668-32.88-8.668h-52.346c-4.145 0-6.435 2.073-6.87 6.214l-21.265 133.48c-0.221 1.311 0.107 2.51 0.981 3.6 0.869 1.093 1.962 1.636 3.271 1.636h24.864c4.361 0 6.758-2.068 7.198-6.216l5.888-35.985c0.215-1.744 0.982-3.162 2.291-4.254 1.308-1.09 2.944-1.804 4.907-2.13 1.963-0.324 3.814-0.487 5.562-0.487 1.743 0 3.814 0.11 6.217 0.327 2.397 0.218 3.925 0.324 4.58 0.324 18.756 0 33.478-5.285 44.167-15.866 10.684-10.577 16.032-25.244 16.032-44.004 0-12.868-4.202-22.192-12.597-27.975zm-26.99 40.08c-1.094 7.635-3.926 12.649-8.506 15.049-4.581 2.403-11.124 3.597-19.629 3.597l-10.797 0.328 5.563-35.007c0.434-2.397 1.851-3.597 4.252-3.597h6.218c8.72 0 15.049 1.257 18.975 3.761 3.924 2.51 5.233 7.802 3.924 15.869z" fill="#003087"/><path d="m720.79 161.18h-24.208c-2.405 0-3.821 1.2-4.253 3.599l-21.267 136.1-0.328 0.654c0 1.096 0.437 2.127 1.311 3.109 0.868 0.979 1.963 1.471 3.271 1.471h21.595c4.138 0 6.429-2.068 6.871-6.215l21.265-133.81v-0.325c-2e-3 -3.053-1.424-4.58-4.257-4.58z" fill="#009CDE"/><path d="m428.31 213.86c0-1.088-0.438-2.126-1.306-3.106-0.875-0.981-1.857-1.474-2.945-1.474h-25.191c-2.404 0-4.366 1.096-5.89 3.271l-34.679 51.04-14.394-49.075c-1.096-3.488-3.493-5.236-7.198-5.236h-24.54c-1.093 0-2.075 0.492-2.942 1.474-0.875 0.98-1.309 2.019-1.309 3.106 0 0.44 2.127 6.871 6.379 19.303 4.252 12.434 8.833 25.848 13.741 40.244 4.908 14.394 7.468 22.031 7.688 22.898-17.886 24.43-26.826 37.518-26.826 39.26 0 2.838 1.417 4.254 4.253 4.254h25.191c2.399 0 4.361-1.088 5.89-3.271l83.427-120.4c0.433-0.433 0.651-1.193 0.651-2.289z" fill="#003087"/><path d="m662.89 209.28h-24.865c-3.056 0-4.904 3.599-5.559 10.797-5.677-8.72-16.031-13.088-31.083-13.088-15.704 0-29.065 5.89-40.077 17.668-11.016 11.779-16.521 25.631-16.521 41.551 0 12.871 3.761 23.121 11.285 30.752 7.524 7.639 17.611 11.451 30.266 11.451 6.323 0 12.757-1.311 19.3-3.926 6.544-2.617 11.665-6.105 15.379-10.469 0 0.219-0.222 1.198-0.654 2.942-0.44 1.748-0.655 3.06-0.655 3.926 0 3.494 1.414 5.234 4.254 5.234h22.576c4.138 0 6.541-2.068 7.193-6.216l13.415-85.389c0.215-1.309-0.111-2.507-0.981-3.599-0.876-1.087-1.964-1.634-3.273-1.634zm-42.694 64.452c-5.562 5.453-12.269 8.179-20.12 8.179-6.328 0-11.449-1.742-15.377-5.234-3.928-3.483-5.891-8.282-5.891-14.396 0-8.064 2.727-14.884 8.181-20.446 5.446-5.562 12.214-8.343 20.284-8.343 6.102 0 11.174 1.8 15.212 5.397 4.032 3.599 6.055 8.563 6.055 14.888-1e-3 7.851-2.783 14.505-8.344 19.955z" fill="#009CDE"/><path d="m291.23 209.28h-24.864c-3.058 0-4.908 3.599-5.563 10.797-5.889-8.72-16.25-13.088-31.081-13.088-15.704 0-29.065 5.89-40.078 17.668-11.016 11.779-16.521 25.631-16.521 41.551 0 12.871 3.763 23.121 11.288 30.752 7.525 7.639 17.61 11.451 30.262 11.451 6.104 0 12.433-1.311 18.975-3.926 6.543-2.617 11.778-6.105 15.704-10.469-0.875 2.616-1.309 4.907-1.309 6.868 0 3.494 1.417 5.234 4.253 5.234h22.574c4.141 0 6.543-2.068 7.198-6.216l13.413-85.389c0.215-1.309-0.112-2.507-0.981-3.599-0.873-1.087-1.962-1.634-3.27-1.634zm-42.695 64.614c-5.563 5.351-12.382 8.017-20.447 8.017-6.329 0-11.4-1.742-15.214-5.234-3.819-3.483-5.726-8.282-5.726-14.396 0-8.064 2.725-14.884 8.18-20.446 5.449-5.562 12.211-8.343 20.284-8.343 6.104 0 11.175 1.8 15.214 5.398 4.032 3.599 6.052 8.563 6.052 14.888 0 8.069-2.781 14.778-8.343 20.116z" fill="#003087"/><path d="m540.04 169.85c-8.398-5.774-19.356-8.668-32.879-8.668h-52.02c-4.364 0-6.765 2.073-7.197 6.214l-21.266 133.48c-0.221 1.312 0.106 2.511 0.981 3.601 0.865 1.092 1.962 1.635 3.271 1.635h26.826c2.617 0 4.361-1.416 5.235-4.252l5.89-37.949c0.216-1.744 0.98-3.162 2.29-4.254 1.309-1.09 2.943-1.803 4.908-2.13 1.962-0.324 3.812-0.487 5.562-0.487 1.743 0 3.814 0.11 6.214 0.327 2.399 0.218 3.931 0.324 4.58 0.324 18.76 0 33.479-5.285 44.168-15.866 10.688-10.577 16.031-25.244 16.031-44.004 2e-3 -12.867-4.199-22.191-12.594-27.974zm-33.534 53.82c-4.799 3.271-11.997 4.906-21.592 4.906l-10.47 0.328 5.562-35.007c0.432-2.397 1.849-3.597 4.252-3.597h5.887c4.798 0 8.614 0.218 11.454 0.653 2.831 0.44 5.562 1.799 8.179 4.089 2.618 2.291 3.926 5.618 3.926 9.98 0 9.16-2.402 15.375-7.198 18.648z" fill="#009CDE"/></svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
1
public/assets/icons/unionpay.svg
Executable file
|
After Width: | Height: | Size: 9.5 KiB |
1
public/assets/icons/visa.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="780" height="500" enable-background="new 0 0 780 500" version="1.1" viewBox="0 0 780 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M40,0h700c22.092,0,40,17.909,40,40v420c0,22.092-17.908,40-40,40H40c-22.091,0-40-17.908-40-40V40 C0,17.909,17.909,0,40,0z" fill="#0E4595"/><path d="m293.2 348.73l33.361-195.76h53.36l-33.385 195.76h-53.336zm246.11-191.54c-10.57-3.966-27.137-8.222-47.822-8.222-52.725 0-89.865 26.55-90.18 64.603-0.299 28.13 26.514 43.822 46.752 53.186 20.771 9.595 27.752 15.714 27.654 24.283-0.131 13.121-16.586 19.116-31.922 19.116-21.357 0-32.703-2.967-50.227-10.276l-6.876-3.11-7.489 43.823c12.463 5.464 35.51 10.198 59.438 10.443 56.09 0 92.5-26.246 92.916-66.882 0.199-22.269-14.016-39.216-44.801-53.188-18.65-9.055-30.072-15.099-29.951-24.268 0-8.137 9.668-16.839 30.557-16.839 17.449-0.27 30.09 3.535 39.938 7.5l4.781 2.26 7.232-42.429m137.31-4.223h-41.232c-12.773 0-22.332 3.487-27.941 16.234l-79.244 179.4h56.031s9.16-24.123 11.232-29.418c6.125 0 60.555 0.084 68.338 0.084 1.596 6.853 6.49 29.334 6.49 29.334h49.514l-43.188-195.64zm-65.418 126.41c4.412-11.279 21.26-54.723 21.26-54.723-0.316 0.522 4.379-11.334 7.074-18.684l3.605 16.879s10.219 46.729 12.354 56.528h-44.293zm-363.3-126.41l-52.24 133.5-5.567-27.13c-9.725-31.273-40.025-65.155-73.898-82.118l47.766 171.2 56.456-0.064 84.004-195.39h-56.521" fill="#fff"/><path d="m146.92 152.96h-86.041l-0.681 4.073c66.938 16.204 111.23 55.363 129.62 102.41l-18.71-89.96c-3.23-12.395-12.597-16.094-24.186-16.527" fill="#F2AE14"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,253 +1,287 @@
|
||||
{
|
||||
"/js/main.js": "/js/main.js",
|
||||
"/css/app.css": "/css/app.css",
|
||||
"/js/main.db73e300d42a147d92c9.hot-update.js": "/js/main.db73e300d42a147d92c9.hot-update.js",
|
||||
"/js/main.0ea5df0b535e6454abdc.hot-update.js": "/js/main.0ea5df0b535e6454abdc.hot-update.js",
|
||||
"/js/main.2cda68eaebe1626133c7.hot-update.js": "/js/main.2cda68eaebe1626133c7.hot-update.js",
|
||||
"/js/main.88f0e74490296b17f12b.hot-update.js": "/js/main.88f0e74490296b17f12b.hot-update.js",
|
||||
"/js/main.8ba41725bdb9b08ea41b.hot-update.js": "/js/main.8ba41725bdb9b08ea41b.hot-update.js",
|
||||
"/js/main.7b5e66db24a0d8fffc66.hot-update.js": "/js/main.7b5e66db24a0d8fffc66.hot-update.js",
|
||||
"/js/main.e44f7ecf17c7e0268ae4.hot-update.js": "/js/main.e44f7ecf17c7e0268ae4.hot-update.js",
|
||||
"/js/main.6749d2651a3d98182751.hot-update.js": "/js/main.6749d2651a3d98182751.hot-update.js",
|
||||
"/js/main.5c564e162157c5e6fb80.hot-update.js": "/js/main.5c564e162157c5e6fb80.hot-update.js",
|
||||
"/js/main.c6a1574884392a89cbaa.hot-update.js": "/js/main.c6a1574884392a89cbaa.hot-update.js",
|
||||
"/js/main.cdebd19025c701560b92.hot-update.js": "/js/main.cdebd19025c701560b92.hot-update.js",
|
||||
"/js/main.f896b7d13aad9732ad0e.hot-update.js": "/js/main.f896b7d13aad9732ad0e.hot-update.js",
|
||||
"/js/main.14e6ae82553043793d06.hot-update.js": "/js/main.14e6ae82553043793d06.hot-update.js",
|
||||
"/js/main.e1d8968eaca9c7a94e14.hot-update.js": "/js/main.e1d8968eaca9c7a94e14.hot-update.js",
|
||||
"/js/main.ee5e426715877748a226.hot-update.js": "/js/main.ee5e426715877748a226.hot-update.js",
|
||||
"/js/main.54454754153a4b810c68.hot-update.js": "/js/main.54454754153a4b810c68.hot-update.js",
|
||||
"/js/main.73250572619a4dca0d35.hot-update.js": "/js/main.73250572619a4dca0d35.hot-update.js",
|
||||
"/js/main.4dbe97b31e06a3c1bebf.hot-update.js": "/js/main.4dbe97b31e06a3c1bebf.hot-update.js",
|
||||
"/js/main.809268a1e86deba22298.hot-update.js": "/js/main.809268a1e86deba22298.hot-update.js",
|
||||
"/js/main.4490e500053d12748641.hot-update.js": "/js/main.4490e500053d12748641.hot-update.js",
|
||||
"/js/main.3953c82fcb9e8aa236f4.hot-update.js": "/js/main.3953c82fcb9e8aa236f4.hot-update.js",
|
||||
"/js/main.90a12056f475838d806c.hot-update.js": "/js/main.90a12056f475838d806c.hot-update.js",
|
||||
"/js/main.fba13eb0d8bdc2de63f9.hot-update.js": "/js/main.fba13eb0d8bdc2de63f9.hot-update.js",
|
||||
"/js/main.2d77e5427d4b8b55419b.hot-update.js": "/js/main.2d77e5427d4b8b55419b.hot-update.js",
|
||||
"/js/main.966dba3cdb08000411ae.hot-update.js": "/js/main.966dba3cdb08000411ae.hot-update.js",
|
||||
"/js/main.8a320a785898586b8d10.hot-update.js": "/js/main.8a320a785898586b8d10.hot-update.js",
|
||||
"/js/main.28edbc28a0031b3f4913.hot-update.js": "/js/main.28edbc28a0031b3f4913.hot-update.js",
|
||||
"/js/main.79eb3750c72852c42485.hot-update.js": "/js/main.79eb3750c72852c42485.hot-update.js",
|
||||
"/js/main.9703ef1a8f855482838f.hot-update.js": "/js/main.9703ef1a8f855482838f.hot-update.js",
|
||||
"/js/main.1cbfcf8465e5d6aa0096.hot-update.js": "/js/main.1cbfcf8465e5d6aa0096.hot-update.js",
|
||||
"/js/main.f1e7b129d14fc15d72e8.hot-update.js": "/js/main.f1e7b129d14fc15d72e8.hot-update.js",
|
||||
"/js/main.58f0f9d441ec01c7d553.hot-update.js": "/js/main.58f0f9d441ec01c7d553.hot-update.js",
|
||||
"/js/main.45858a0dfab5dd3a911a.hot-update.js": "/js/main.45858a0dfab5dd3a911a.hot-update.js",
|
||||
"/js/main.ade5cf3ef31b2e506425.hot-update.js": "/js/main.ade5cf3ef31b2e506425.hot-update.js",
|
||||
"/js/main.c4304b2de45e8f06f7b5.hot-update.js": "/js/main.c4304b2de45e8f06f7b5.hot-update.js",
|
||||
"/js/main.0961cf18a9605cb65e3f.hot-update.js": "/js/main.0961cf18a9605cb65e3f.hot-update.js",
|
||||
"/js/main.5a371d0e098a933c4640.hot-update.js": "/js/main.5a371d0e098a933c4640.hot-update.js",
|
||||
"/js/main.d3c2f6bd4ce092746115.hot-update.js": "/js/main.d3c2f6bd4ce092746115.hot-update.js",
|
||||
"/js/main.e191340cc52008653ed0.hot-update.js": "/js/main.e191340cc52008653ed0.hot-update.js",
|
||||
"/js/main.3cb43f27a625a07fcc0b.hot-update.js": "/js/main.3cb43f27a625a07fcc0b.hot-update.js",
|
||||
"/js/main.1410e64aed21b84592e7.hot-update.js": "/js/main.1410e64aed21b84592e7.hot-update.js",
|
||||
"/js/main.08a6a51c0acea91879f7.hot-update.js": "/js/main.08a6a51c0acea91879f7.hot-update.js",
|
||||
"/js/main.f3a5ecf31e3df2d23957.hot-update.js": "/js/main.f3a5ecf31e3df2d23957.hot-update.js",
|
||||
"/js/main.7c67297040c94f2a585e.hot-update.js": "/js/main.7c67297040c94f2a585e.hot-update.js",
|
||||
"/js/main.d7c58200175c3d4ab962.hot-update.js": "/js/main.d7c58200175c3d4ab962.hot-update.js",
|
||||
"/js/main.58979cee95bba3ec04c5.hot-update.js": "/js/main.58979cee95bba3ec04c5.hot-update.js",
|
||||
"/js/main.94f329f8b9d0aa2d4182.hot-update.js": "/js/main.94f329f8b9d0aa2d4182.hot-update.js",
|
||||
"/js/main.23a1f3a1d28f2b39e1b7.hot-update.js": "/js/main.23a1f3a1d28f2b39e1b7.hot-update.js",
|
||||
"/js/main.a7df7455225c5d05227f.hot-update.js": "/js/main.a7df7455225c5d05227f.hot-update.js",
|
||||
"/js/main.7b16550bbd8be6cc9b8d.hot-update.js": "/js/main.7b16550bbd8be6cc9b8d.hot-update.js",
|
||||
"/js/main.780968811eb17fef25a7.hot-update.js": "/js/main.780968811eb17fef25a7.hot-update.js",
|
||||
"/js/main.aad31e3890b61350c4fa.hot-update.js": "/js/main.aad31e3890b61350c4fa.hot-update.js",
|
||||
"/js/main.41b4b985c13b8890717d.hot-update.js": "/js/main.41b4b985c13b8890717d.hot-update.js",
|
||||
"/js/main.e025100d60c74d0392d1.hot-update.js": "/js/main.e025100d60c74d0392d1.hot-update.js",
|
||||
"/js/main.67661103ba5d1dd3cac6.hot-update.js": "/js/main.67661103ba5d1dd3cac6.hot-update.js",
|
||||
"/js/main.4859f6f2e961eba13edf.hot-update.js": "/js/main.4859f6f2e961eba13edf.hot-update.js",
|
||||
"/js/main.2412ccd7b9afcb3dd059.hot-update.js": "/js/main.2412ccd7b9afcb3dd059.hot-update.js",
|
||||
"/js/main.0a9300e8875685257a5a.hot-update.js": "/js/main.0a9300e8875685257a5a.hot-update.js",
|
||||
"/js/main.6e32369655d811852893.hot-update.js": "/js/main.6e32369655d811852893.hot-update.js",
|
||||
"/js/main.07e4dcb8b14f80943019.hot-update.js": "/js/main.07e4dcb8b14f80943019.hot-update.js",
|
||||
"/js/main.a970e8749724b2c1488f.hot-update.js": "/js/main.a970e8749724b2c1488f.hot-update.js",
|
||||
"/js/main.26c44e4e22a245d1e8a9.hot-update.js": "/js/main.26c44e4e22a245d1e8a9.hot-update.js",
|
||||
"/js/main.de6ddacb5c245c079fab.hot-update.js": "/js/main.de6ddacb5c245c079fab.hot-update.js",
|
||||
"/js/main.564a42509ff2e25ba549.hot-update.js": "/js/main.564a42509ff2e25ba549.hot-update.js",
|
||||
"/js/main.c63aad49b7cd674b91a7.hot-update.js": "/js/main.c63aad49b7cd674b91a7.hot-update.js",
|
||||
"/js/main.81931bb64710a2f54368.hot-update.js": "/js/main.81931bb64710a2f54368.hot-update.js",
|
||||
"/js/main.34efd0ebe70125b4d9cd.hot-update.js": "/js/main.34efd0ebe70125b4d9cd.hot-update.js",
|
||||
"/js/main.3de56aa8af78d2912a79.hot-update.js": "/js/main.3de56aa8af78d2912a79.hot-update.js",
|
||||
"/js/main.3492d8df8ba23f79e39f.hot-update.js": "/js/main.3492d8df8ba23f79e39f.hot-update.js",
|
||||
"/js/main.1a1f505e34d61bf5c741.hot-update.js": "/js/main.1a1f505e34d61bf5c741.hot-update.js",
|
||||
"/js/main.7d6fa20346e95f934020.hot-update.js": "/js/main.7d6fa20346e95f934020.hot-update.js",
|
||||
"/js/main.e5fa1224b06e6203aaa4.hot-update.js": "/js/main.e5fa1224b06e6203aaa4.hot-update.js",
|
||||
"/js/main.a2e4f55324730e0a1137.hot-update.js": "/js/main.a2e4f55324730e0a1137.hot-update.js",
|
||||
"/js/main.82081e3a97b9075cbf38.hot-update.js": "/js/main.82081e3a97b9075cbf38.hot-update.js",
|
||||
"/js/main.ab06dcdaa2fc897e4576.hot-update.js": "/js/main.ab06dcdaa2fc897e4576.hot-update.js",
|
||||
"/js/main.8aee157f69acbf01d692.hot-update.js": "/js/main.8aee157f69acbf01d692.hot-update.js",
|
||||
"/js/main.82087e18f1767795f3cc.hot-update.js": "/js/main.82087e18f1767795f3cc.hot-update.js",
|
||||
"/js/main.f2c483d7d1261df861b3.hot-update.js": "/js/main.f2c483d7d1261df861b3.hot-update.js",
|
||||
"/js/main.ef75264f1a02af5ca3cd.hot-update.js": "/js/main.ef75264f1a02af5ca3cd.hot-update.js",
|
||||
"/js/main.cd61e67651fe4e61f358.hot-update.js": "/js/main.cd61e67651fe4e61f358.hot-update.js",
|
||||
"/js/main.97ba89c984ffe538a333.hot-update.js": "/js/main.97ba89c984ffe538a333.hot-update.js",
|
||||
"/js/main.a23de6f4cea6b80806b4.hot-update.js": "/js/main.a23de6f4cea6b80806b4.hot-update.js",
|
||||
"/js/main.90440654186ae45a6f63.hot-update.js": "/js/main.90440654186ae45a6f63.hot-update.js",
|
||||
"/js/main.483297e74b80dfdc50c3.hot-update.js": "/js/main.483297e74b80dfdc50c3.hot-update.js",
|
||||
"/js/main.e2831389d5cdf78e4bd3.hot-update.js": "/js/main.e2831389d5cdf78e4bd3.hot-update.js",
|
||||
"/js/main.3af60e2033e8130d75f6.hot-update.js": "/js/main.3af60e2033e8130d75f6.hot-update.js",
|
||||
"/js/main.1b1ac80d4947b920ea2f.hot-update.js": "/js/main.1b1ac80d4947b920ea2f.hot-update.js",
|
||||
"/js/main.8a52e7d2eff934f9de4d.hot-update.js": "/js/main.8a52e7d2eff934f9de4d.hot-update.js",
|
||||
"/js/main.b67e5558feff737183b6.hot-update.js": "/js/main.b67e5558feff737183b6.hot-update.js",
|
||||
"/js/main.2202ff72b0fe9ff3f0c2.hot-update.js": "/js/main.2202ff72b0fe9ff3f0c2.hot-update.js",
|
||||
"/js/main.d9cb8d8e4ca7d410b22f.hot-update.js": "/js/main.d9cb8d8e4ca7d410b22f.hot-update.js",
|
||||
"/js/main.a1d688c433c9fcf14bab.hot-update.js": "/js/main.a1d688c433c9fcf14bab.hot-update.js",
|
||||
"/js/main.b2cf91ae6a0fbc682e64.hot-update.js": "/js/main.b2cf91ae6a0fbc682e64.hot-update.js",
|
||||
"/js/main.63e1d96c978ec4ca4e3a.hot-update.js": "/js/main.63e1d96c978ec4ca4e3a.hot-update.js",
|
||||
"/js/main.6e476cf8eabaf496f17a.hot-update.js": "/js/main.6e476cf8eabaf496f17a.hot-update.js",
|
||||
"/js/main.fa9bfaf5cf5b454739e7.hot-update.js": "/js/main.fa9bfaf5cf5b454739e7.hot-update.js",
|
||||
"/js/main.b246393843e1e04d1472.hot-update.js": "/js/main.b246393843e1e04d1472.hot-update.js",
|
||||
"/js/main.cfeac3c0594ca2e18cbc.hot-update.js": "/js/main.cfeac3c0594ca2e18cbc.hot-update.js",
|
||||
"/js/main.ffaf8712fd1cd702ea8a.hot-update.js": "/js/main.ffaf8712fd1cd702ea8a.hot-update.js",
|
||||
"/js/main.1a9b77d1d99fa0cbe049.hot-update.js": "/js/main.1a9b77d1d99fa0cbe049.hot-update.js",
|
||||
"/js/main.35f70fbeab261f617c64.hot-update.js": "/js/main.35f70fbeab261f617c64.hot-update.js",
|
||||
"/js/main.2adec493e4879764b552.hot-update.js": "/js/main.2adec493e4879764b552.hot-update.js",
|
||||
"/js/main.84e27e090764f99a5f8d.hot-update.js": "/js/main.84e27e090764f99a5f8d.hot-update.js",
|
||||
"/js/main.d5fad1aae15440174c3b.hot-update.js": "/js/main.d5fad1aae15440174c3b.hot-update.js",
|
||||
"/js/main.f082a5aa1a7d811653b0.hot-update.js": "/js/main.f082a5aa1a7d811653b0.hot-update.js",
|
||||
"/js/main.cd15a772e4d701a910b1.hot-update.js": "/js/main.cd15a772e4d701a910b1.hot-update.js",
|
||||
"/js/main.1e62178bd569cacdace7.hot-update.js": "/js/main.1e62178bd569cacdace7.hot-update.js",
|
||||
"/js/main.19bca5f612f96fe6d127.hot-update.js": "/js/main.19bca5f612f96fe6d127.hot-update.js",
|
||||
"/js/main.c775d381b77c164f7fc4.hot-update.js": "/js/main.c775d381b77c164f7fc4.hot-update.js",
|
||||
"/js/main.f8c6cffd1559d9578b83.hot-update.js": "/js/main.f8c6cffd1559d9578b83.hot-update.js",
|
||||
"/js/main.c7ff369b0854108f96c7.hot-update.js": "/js/main.c7ff369b0854108f96c7.hot-update.js",
|
||||
"/js/main.062ff67378e519023a1e.hot-update.js": "/js/main.062ff67378e519023a1e.hot-update.js",
|
||||
"/js/main.6e66fc4d78272a71315e.hot-update.js": "/js/main.6e66fc4d78272a71315e.hot-update.js",
|
||||
"/js/main.a8e90242995935949f17.hot-update.js": "/js/main.a8e90242995935949f17.hot-update.js",
|
||||
"/js/main.4e224f3aad42c7f5ed0b.hot-update.js": "/js/main.4e224f3aad42c7f5ed0b.hot-update.js",
|
||||
"/js/main.385eb38db8eb0702b502.hot-update.js": "/js/main.385eb38db8eb0702b502.hot-update.js",
|
||||
"/js/main.996d84214f93de3c1c0b.hot-update.js": "/js/main.996d84214f93de3c1c0b.hot-update.js",
|
||||
"/js/main.38d70851a7c72784d66d.hot-update.js": "/js/main.38d70851a7c72784d66d.hot-update.js",
|
||||
"/js/main.dbbfab82de065b7b60cd.hot-update.js": "/js/main.dbbfab82de065b7b60cd.hot-update.js",
|
||||
"/js/main.574aea784108ee1eac07.hot-update.js": "/js/main.574aea784108ee1eac07.hot-update.js",
|
||||
"/js/main.9de756c799555e75db7d.hot-update.js": "/js/main.9de756c799555e75db7d.hot-update.js",
|
||||
"/js/main.83ab95777680fb06e0aa.hot-update.js": "/js/main.83ab95777680fb06e0aa.hot-update.js",
|
||||
"/js/main.e666c42f96b6bdb22969.hot-update.js": "/js/main.e666c42f96b6bdb22969.hot-update.js",
|
||||
"/js/main.03428097b17bfe163a16.hot-update.js": "/js/main.03428097b17bfe163a16.hot-update.js",
|
||||
"/js/main.05d6a5f7f8c614a903e8.hot-update.js": "/js/main.05d6a5f7f8c614a903e8.hot-update.js",
|
||||
"/js/main.7d8ff39260c5f281d28f.hot-update.js": "/js/main.7d8ff39260c5f281d28f.hot-update.js",
|
||||
"/js/main.ad2349f007227d33ace3.hot-update.js": "/js/main.ad2349f007227d33ace3.hot-update.js",
|
||||
"/js/main.61787afe25ca75dad5ec.hot-update.js": "/js/main.61787afe25ca75dad5ec.hot-update.js",
|
||||
"/js/main.f130f7974630d2357291.hot-update.js": "/js/main.f130f7974630d2357291.hot-update.js",
|
||||
"/js/main.194f15b84f0ba10c3558.hot-update.js": "/js/main.194f15b84f0ba10c3558.hot-update.js",
|
||||
"/js/main.c9d4446b200a7919a284.hot-update.js": "/js/main.c9d4446b200a7919a284.hot-update.js",
|
||||
"/js/main.a8a11f9957cb0472fcb1.hot-update.js": "/js/main.a8a11f9957cb0472fcb1.hot-update.js",
|
||||
"/js/main.15201b3e0fd22133a26a.hot-update.js": "/js/main.15201b3e0fd22133a26a.hot-update.js",
|
||||
"/js/main.24c3c7e84b88e524c006.hot-update.js": "/js/main.24c3c7e84b88e524c006.hot-update.js",
|
||||
"/js/main.4a9d275860a5b9a8d2d2.hot-update.js": "/js/main.4a9d275860a5b9a8d2d2.hot-update.js",
|
||||
"/js/main.1a78e45577ac640daa18.hot-update.js": "/js/main.1a78e45577ac640daa18.hot-update.js",
|
||||
"/js/main.91f804d23d8cd6a0562e.hot-update.js": "/js/main.91f804d23d8cd6a0562e.hot-update.js",
|
||||
"/js/main.37f4690a9d8970b2a997.hot-update.js": "/js/main.37f4690a9d8970b2a997.hot-update.js",
|
||||
"/js/main.39cc460540d3e54e861d.hot-update.js": "/js/main.39cc460540d3e54e861d.hot-update.js",
|
||||
"/js/main.97e2ae5d288287b185a4.hot-update.js": "/js/main.97e2ae5d288287b185a4.hot-update.js",
|
||||
"/js/main.bcaa46e78128bc1ce527.hot-update.js": "/js/main.bcaa46e78128bc1ce527.hot-update.js",
|
||||
"/js/main.f9b275607e4c5781a474.hot-update.js": "/js/main.f9b275607e4c5781a474.hot-update.js",
|
||||
"/js/main.3625f6f0997dd72db8fb.hot-update.js": "/js/main.3625f6f0997dd72db8fb.hot-update.js",
|
||||
"/js/main.8aac94e8b65eb3822505.hot-update.js": "/js/main.8aac94e8b65eb3822505.hot-update.js",
|
||||
"/js/main.962286776eaf79087cff.hot-update.js": "/js/main.962286776eaf79087cff.hot-update.js",
|
||||
"/js/main.a66ab1c4d2fa23744e67.hot-update.js": "/js/main.a66ab1c4d2fa23744e67.hot-update.js",
|
||||
"/js/main.9a1ab04495b8495aa7a3.hot-update.js": "/js/main.9a1ab04495b8495aa7a3.hot-update.js",
|
||||
"/js/main.394df0e7d4886f791e9a.hot-update.js": "/js/main.394df0e7d4886f791e9a.hot-update.js",
|
||||
"/js/main.bbd2e296d4d14fafbc5c.hot-update.js": "/js/main.bbd2e296d4d14fafbc5c.hot-update.js",
|
||||
"/js/main.c9330023b054be206d4d.hot-update.js": "/js/main.c9330023b054be206d4d.hot-update.js",
|
||||
"/js/main.5d81a2f9c58ce58a43cd.hot-update.js": "/js/main.5d81a2f9c58ce58a43cd.hot-update.js",
|
||||
"/js/main.86fa688fb982fbd12aca.hot-update.js": "/js/main.86fa688fb982fbd12aca.hot-update.js",
|
||||
"/js/main.645f6368417b7c4fd590.hot-update.js": "/js/main.645f6368417b7c4fd590.hot-update.js",
|
||||
"/js/main.6edba403d405425e87cf.hot-update.js": "/js/main.6edba403d405425e87cf.hot-update.js",
|
||||
"/js/main.ca0cd44c7d8d17cc9991.hot-update.js": "/js/main.ca0cd44c7d8d17cc9991.hot-update.js",
|
||||
"/js/main.b831183422933c78119c.hot-update.js": "/js/main.b831183422933c78119c.hot-update.js",
|
||||
"/js/main.80db7eb954bc974b52ec.hot-update.js": "/js/main.80db7eb954bc974b52ec.hot-update.js",
|
||||
"/js/main.8bee745b28ee104901f8.hot-update.js": "/js/main.8bee745b28ee104901f8.hot-update.js",
|
||||
"/js/main.e0e4ec61d482c4f3dbe8.hot-update.js": "/js/main.e0e4ec61d482c4f3dbe8.hot-update.js",
|
||||
"/js/main.bb3ed5bb83568a1abbda.hot-update.js": "/js/main.bb3ed5bb83568a1abbda.hot-update.js",
|
||||
"/js/main.0fca3fcc3088a5f8b7e0.hot-update.js": "/js/main.0fca3fcc3088a5f8b7e0.hot-update.js",
|
||||
"/js/main.fb7b96cb40ab22050c79.hot-update.js": "/js/main.fb7b96cb40ab22050c79.hot-update.js",
|
||||
"/js/main.9348fa55f71efc5060b8.hot-update.js": "/js/main.9348fa55f71efc5060b8.hot-update.js",
|
||||
"/js/main.0122b6629f01a705476d.hot-update.js": "/js/main.0122b6629f01a705476d.hot-update.js",
|
||||
"/js/main.ffc029e04518fabf33cd.hot-update.js": "/js/main.ffc029e04518fabf33cd.hot-update.js",
|
||||
"/js/main.0666ac365d039c279130.hot-update.js": "/js/main.0666ac365d039c279130.hot-update.js",
|
||||
"/js/main.844c2113c0c54845083c.hot-update.js": "/js/main.844c2113c0c54845083c.hot-update.js",
|
||||
"/js/main.04c649da59688caed7f4.hot-update.js": "/js/main.04c649da59688caed7f4.hot-update.js",
|
||||
"/js/main.df8852739b6eb0d8ddd8.hot-update.js": "/js/main.df8852739b6eb0d8ddd8.hot-update.js",
|
||||
"/js/main.2bb035b765159291e6d4.hot-update.js": "/js/main.2bb035b765159291e6d4.hot-update.js",
|
||||
"/js/main.6eb45c6e294e847c45ea.hot-update.js": "/js/main.6eb45c6e294e847c45ea.hot-update.js",
|
||||
"/js/main.c6070c2ada89c43fa419.hot-update.js": "/js/main.c6070c2ada89c43fa419.hot-update.js",
|
||||
"/js/main.f828168b89124130bc68.hot-update.js": "/js/main.f828168b89124130bc68.hot-update.js",
|
||||
"/js/main.e5eb5a13e710543f7bd9.hot-update.js": "/js/main.e5eb5a13e710543f7bd9.hot-update.js",
|
||||
"/js/main.63b69c5bbda8f437d459.hot-update.js": "/js/main.63b69c5bbda8f437d459.hot-update.js",
|
||||
"/js/main.a72c8891596b66b212b6.hot-update.js": "/js/main.a72c8891596b66b212b6.hot-update.js",
|
||||
"/js/main.19e0710bc40f03b262e6.hot-update.js": "/js/main.19e0710bc40f03b262e6.hot-update.js",
|
||||
"/js/main.0134afb94f91a4a36def.hot-update.js": "/js/main.0134afb94f91a4a36def.hot-update.js",
|
||||
"/js/main.9a24933aefa3e49663f7.hot-update.js": "/js/main.9a24933aefa3e49663f7.hot-update.js",
|
||||
"/js/main.cc27c9bc9c27f1b845bb.hot-update.js": "/js/main.cc27c9bc9c27f1b845bb.hot-update.js",
|
||||
"/js/main.b93834f4ca3df91cd540.hot-update.js": "/js/main.b93834f4ca3df91cd540.hot-update.js",
|
||||
"/js/main.5937cb7e39356fd7d4c4.hot-update.js": "/js/main.5937cb7e39356fd7d4c4.hot-update.js",
|
||||
"/js/main.cea013f04296667aee3a.hot-update.js": "/js/main.cea013f04296667aee3a.hot-update.js",
|
||||
"/js/main.bff0613b9adee03ca219.hot-update.js": "/js/main.bff0613b9adee03ca219.hot-update.js",
|
||||
"/js/main.a43ba373208207664417.hot-update.js": "/js/main.a43ba373208207664417.hot-update.js",
|
||||
"/js/main.4ff290116a377da3d41f.hot-update.js": "/js/main.4ff290116a377da3d41f.hot-update.js",
|
||||
"/js/main.96a5134be5a0a98693e4.hot-update.js": "/js/main.96a5134be5a0a98693e4.hot-update.js",
|
||||
"/js/main.e0432d1e9c7975c2ab9d.hot-update.js": "/js/main.e0432d1e9c7975c2ab9d.hot-update.js",
|
||||
"/js/main.d62433ce757652be6f54.hot-update.js": "/js/main.d62433ce757652be6f54.hot-update.js",
|
||||
"/js/main.fa91e0076416ce9b9eac.hot-update.js": "/js/main.fa91e0076416ce9b9eac.hot-update.js",
|
||||
"/js/main.6791a0db3468e2abbb01.hot-update.js": "/js/main.6791a0db3468e2abbb01.hot-update.js",
|
||||
"/js/main.f34c60f7b8d27d185789.hot-update.js": "/js/main.f34c60f7b8d27d185789.hot-update.js",
|
||||
"/js/main.e0ac013a5685366884b0.hot-update.js": "/js/main.e0ac013a5685366884b0.hot-update.js",
|
||||
"/js/main.45f929f9501bca0a3a2b.hot-update.js": "/js/main.45f929f9501bca0a3a2b.hot-update.js",
|
||||
"/js/main.c17c98fa0aac463d62ec.hot-update.js": "/js/main.c17c98fa0aac463d62ec.hot-update.js",
|
||||
"/js/main.0e03c020348420598462.hot-update.js": "/js/main.0e03c020348420598462.hot-update.js",
|
||||
"/js/main.0a76373d676f6bc3f8b7.hot-update.js": "/js/main.0a76373d676f6bc3f8b7.hot-update.js",
|
||||
"/js/main.7d0b5e6140d5a76d8a6e.hot-update.js": "/js/main.7d0b5e6140d5a76d8a6e.hot-update.js",
|
||||
"/js/main.5faa42142a298e5ab92b.hot-update.js": "/js/main.5faa42142a298e5ab92b.hot-update.js",
|
||||
"/js/main.3eaf20665f37c24473fd.hot-update.js": "/js/main.3eaf20665f37c24473fd.hot-update.js",
|
||||
"/js/main.6d0cf380525ddd49bb4b.hot-update.js": "/js/main.6d0cf380525ddd49bb4b.hot-update.js",
|
||||
"/js/main.96ceb1a99c9ccca2fbbe.hot-update.js": "/js/main.96ceb1a99c9ccca2fbbe.hot-update.js",
|
||||
"/js/main.3557a28505eb1edad3c6.hot-update.js": "/js/main.3557a28505eb1edad3c6.hot-update.js",
|
||||
"/js/main.f85533ba77bc9daa2b28.hot-update.js": "/js/main.f85533ba77bc9daa2b28.hot-update.js",
|
||||
"/js/main.844ced51412415958d01.hot-update.js": "/js/main.844ced51412415958d01.hot-update.js",
|
||||
"/js/main.4aef58634b3a86124e7f.hot-update.js": "/js/main.4aef58634b3a86124e7f.hot-update.js",
|
||||
"/js/main.6de5f0faf8a05f2fc5a7.hot-update.js": "/js/main.6de5f0faf8a05f2fc5a7.hot-update.js",
|
||||
"/js/main.c62abbf47cf5f738c9b5.hot-update.js": "/js/main.c62abbf47cf5f738c9b5.hot-update.js",
|
||||
"/js/main.87c321a637ae5ab917ce.hot-update.js": "/js/main.87c321a637ae5ab917ce.hot-update.js",
|
||||
"/js/main.90ad40b9a9f360d249f9.hot-update.js": "/js/main.90ad40b9a9f360d249f9.hot-update.js",
|
||||
"/js/main.91b09e11f41e643af61b.hot-update.js": "/js/main.91b09e11f41e643af61b.hot-update.js",
|
||||
"/js/main.6e993020f81c4506f7f1.hot-update.js": "/js/main.6e993020f81c4506f7f1.hot-update.js",
|
||||
"/js/main.eb69554875d7f6f0af13.hot-update.js": "/js/main.eb69554875d7f6f0af13.hot-update.js",
|
||||
"/js/main.b00263659caf576e365f.hot-update.js": "/js/main.b00263659caf576e365f.hot-update.js",
|
||||
"/js/main.3731a12d7df03dd0b1ac.hot-update.js": "/js/main.3731a12d7df03dd0b1ac.hot-update.js",
|
||||
"/js/main.14283c0c8928f2bac642.hot-update.js": "/js/main.14283c0c8928f2bac642.hot-update.js",
|
||||
"/js/main.5d22154675bb7301f3c3.hot-update.js": "/js/main.5d22154675bb7301f3c3.hot-update.js",
|
||||
"/js/main.68f901614ec25bb9be2e.hot-update.js": "/js/main.68f901614ec25bb9be2e.hot-update.js",
|
||||
"/js/main.94b2828776f652bbecd1.hot-update.js": "/js/main.94b2828776f652bbecd1.hot-update.js",
|
||||
"/js/main.a5193c2c4b1f57e843ac.hot-update.js": "/js/main.a5193c2c4b1f57e843ac.hot-update.js",
|
||||
"/js/main.50b2e366bd6b72990a03.hot-update.js": "/js/main.50b2e366bd6b72990a03.hot-update.js",
|
||||
"/js/main.f7a87e8ee0dc7a8c3d35.hot-update.js": "/js/main.f7a87e8ee0dc7a8c3d35.hot-update.js",
|
||||
"/js/main.460fb4a8eadec50eafc0.hot-update.js": "/js/main.460fb4a8eadec50eafc0.hot-update.js",
|
||||
"/js/main.b56efb8b6dda94e0e837.hot-update.js": "/js/main.b56efb8b6dda94e0e837.hot-update.js",
|
||||
"/js/main.7696e7ea10b668afeccc.hot-update.js": "/js/main.7696e7ea10b668afeccc.hot-update.js",
|
||||
"/js/main.7d32beb20b5719f11726.hot-update.js": "/js/main.7d32beb20b5719f11726.hot-update.js",
|
||||
"/js/main.6325449e7341db20a9ce.hot-update.js": "/js/main.6325449e7341db20a9ce.hot-update.js",
|
||||
"/js/main.2cc0ebd3eba768b8429c.hot-update.js": "/js/main.2cc0ebd3eba768b8429c.hot-update.js",
|
||||
"/js/main.22edc66a07d0d7fc8d83.hot-update.js": "/js/main.22edc66a07d0d7fc8d83.hot-update.js",
|
||||
"/js/main.60bed97815a1ea0a09d6.hot-update.js": "/js/main.60bed97815a1ea0a09d6.hot-update.js",
|
||||
"/js/main.f6a63bab2aa5511566e7.hot-update.js": "/js/main.f6a63bab2aa5511566e7.hot-update.js",
|
||||
"/js/main.121e2dd11bc35045482b.hot-update.js": "/js/main.121e2dd11bc35045482b.hot-update.js",
|
||||
"/js/main.541def265ec163ed2d5f.hot-update.js": "/js/main.541def265ec163ed2d5f.hot-update.js",
|
||||
"/js/main.c9814fe8d127f6265fdf.hot-update.js": "/js/main.c9814fe8d127f6265fdf.hot-update.js",
|
||||
"/js/main.0c31610719dd6fbfd7ab.hot-update.js": "/js/main.0c31610719dd6fbfd7ab.hot-update.js",
|
||||
"/js/main.73d20180f790009a0536.hot-update.js": "/js/main.73d20180f790009a0536.hot-update.js",
|
||||
"/js/main.bd8cd2b0d65c5499a5fa.hot-update.js": "/js/main.bd8cd2b0d65c5499a5fa.hot-update.js",
|
||||
"/js/main.4b941ee3158e8f359e0b.hot-update.js": "/js/main.4b941ee3158e8f359e0b.hot-update.js",
|
||||
"/js/main.4eed502c18c3384e017c.hot-update.js": "/js/main.4eed502c18c3384e017c.hot-update.js",
|
||||
"/js/main.0ff9c65b54e9f2fd3f09.hot-update.js": "/js/main.0ff9c65b54e9f2fd3f09.hot-update.js",
|
||||
"/js/main.0c5bcf3373897713488f.hot-update.js": "/js/main.0c5bcf3373897713488f.hot-update.js",
|
||||
"/js/main.5d00a679a40bb2c37b11.hot-update.js": "/js/main.5d00a679a40bb2c37b11.hot-update.js",
|
||||
"/js/main.2559125fe1eef3ee7dd3.hot-update.js": "/js/main.2559125fe1eef3ee7dd3.hot-update.js",
|
||||
"/js/main.55d5f2f55034cb7a4da6.hot-update.js": "/js/main.55d5f2f55034cb7a4da6.hot-update.js",
|
||||
"/js/main.890897a7ce8479317a97.hot-update.js": "/js/main.890897a7ce8479317a97.hot-update.js",
|
||||
"/js/main.988a45b98fc8b8c5e41c.hot-update.js": "/js/main.988a45b98fc8b8c5e41c.hot-update.js",
|
||||
"/js/main.33577380f3a58be208ee.hot-update.js": "/js/main.33577380f3a58be208ee.hot-update.js",
|
||||
"/js/main.ada254f372b54b162118.hot-update.js": "/js/main.ada254f372b54b162118.hot-update.js",
|
||||
"/js/main.afa97b2d282c673884a9.hot-update.js": "/js/main.afa97b2d282c673884a9.hot-update.js"
|
||||
"/js/main.c592c1b513edd7534891.hot-update.js": "/js/main.c592c1b513edd7534891.hot-update.js",
|
||||
"/js/main.80ad9909faceb74207f1.hot-update.js": "/js/main.80ad9909faceb74207f1.hot-update.js",
|
||||
"/js/main.4b91997785e85d7d6e32.hot-update.js": "/js/main.4b91997785e85d7d6e32.hot-update.js",
|
||||
"/js/main.e787780098edc245ae3c.hot-update.js": "/js/main.e787780098edc245ae3c.hot-update.js",
|
||||
"/js/main.e55b17a6a5a315b93bef.hot-update.js": "/js/main.e55b17a6a5a315b93bef.hot-update.js",
|
||||
"/js/main.28fdd591cc524a88c846.hot-update.js": "/js/main.28fdd591cc524a88c846.hot-update.js",
|
||||
"/js/main.2b812942c78e860c03db.hot-update.js": "/js/main.2b812942c78e860c03db.hot-update.js",
|
||||
"/js/main.211081d76c54b5482de5.hot-update.js": "/js/main.211081d76c54b5482de5.hot-update.js",
|
||||
"/js/main.fd6434aee58e09a56ff4.hot-update.js": "/js/main.fd6434aee58e09a56ff4.hot-update.js",
|
||||
"/js/main.4c1d8cba619a7927638c.hot-update.js": "/js/main.4c1d8cba619a7927638c.hot-update.js",
|
||||
"/js/main.aff41805a3b84c8ebae5.hot-update.js": "/js/main.aff41805a3b84c8ebae5.hot-update.js",
|
||||
"/js/main.6f72ba9701b9e19c9be0.hot-update.js": "/js/main.6f72ba9701b9e19c9be0.hot-update.js",
|
||||
"/js/main.0e4c6671c2367b10695d.hot-update.js": "/js/main.0e4c6671c2367b10695d.hot-update.js",
|
||||
"/js/main.1985d2920179f9a6f78f.hot-update.js": "/js/main.1985d2920179f9a6f78f.hot-update.js",
|
||||
"/js/main.9f9975790f0a229f2cb2.hot-update.js": "/js/main.9f9975790f0a229f2cb2.hot-update.js",
|
||||
"/js/main.0fba79cfcfa3990cf559.hot-update.js": "/js/main.0fba79cfcfa3990cf559.hot-update.js",
|
||||
"/js/main.03715cbb9f7cdc53e0ff.hot-update.js": "/js/main.03715cbb9f7cdc53e0ff.hot-update.js",
|
||||
"/js/main.b6aaa5a10b3ddcee7f9d.hot-update.js": "/js/main.b6aaa5a10b3ddcee7f9d.hot-update.js",
|
||||
"/js/main.d7271130fb59906d5182.hot-update.js": "/js/main.d7271130fb59906d5182.hot-update.js",
|
||||
"/js/main.957b7763ea3c9accc8cc.hot-update.js": "/js/main.957b7763ea3c9accc8cc.hot-update.js",
|
||||
"/js/main.e23eea5ec4310f745400.hot-update.js": "/js/main.e23eea5ec4310f745400.hot-update.js",
|
||||
"/js/main.6e342ea527f2c3f9b013.hot-update.js": "/js/main.6e342ea527f2c3f9b013.hot-update.js",
|
||||
"/js/main.612f96382ad8ba3d109c.hot-update.js": "/js/main.612f96382ad8ba3d109c.hot-update.js",
|
||||
"/js/main.aba02ea167c96d2b7634.hot-update.js": "/js/main.aba02ea167c96d2b7634.hot-update.js",
|
||||
"/js/main.9d67410798c6c29f0842.hot-update.js": "/js/main.9d67410798c6c29f0842.hot-update.js",
|
||||
"/js/main.e4515959db9d0f8747f2.hot-update.js": "/js/main.e4515959db9d0f8747f2.hot-update.js",
|
||||
"/js/main.cb089a2ecaf1fd0be078.hot-update.js": "/js/main.cb089a2ecaf1fd0be078.hot-update.js",
|
||||
"/js/main.5ba809ade4770806836a.hot-update.js": "/js/main.5ba809ade4770806836a.hot-update.js",
|
||||
"/js/main.990c352366666e2ca2f2.hot-update.js": "/js/main.990c352366666e2ca2f2.hot-update.js",
|
||||
"/js/main.4c12e8bb7d017220e3fa.hot-update.js": "/js/main.4c12e8bb7d017220e3fa.hot-update.js",
|
||||
"/js/main.0bd1b62237741b506f57.hot-update.js": "/js/main.0bd1b62237741b506f57.hot-update.js",
|
||||
"/js/main.90a24d55baa0b9e45607.hot-update.js": "/js/main.90a24d55baa0b9e45607.hot-update.js",
|
||||
"/js/main.f0152d5ede68576fab2f.hot-update.js": "/js/main.f0152d5ede68576fab2f.hot-update.js",
|
||||
"/js/main.f87dba2f8ad4b673eef3.hot-update.js": "/js/main.f87dba2f8ad4b673eef3.hot-update.js",
|
||||
"/js/main.7738f2b3cc86dadbfcf9.hot-update.js": "/js/main.7738f2b3cc86dadbfcf9.hot-update.js",
|
||||
"/js/main.a6bc9844316ff7a73a3a.hot-update.js": "/js/main.a6bc9844316ff7a73a3a.hot-update.js",
|
||||
"/js/main.30f1c08c6c5c716bc99b.hot-update.js": "/js/main.30f1c08c6c5c716bc99b.hot-update.js",
|
||||
"/js/main.52f9059179cdfa541c49.hot-update.js": "/js/main.52f9059179cdfa541c49.hot-update.js",
|
||||
"/js/main.bd918a21f99459ac0c5a.hot-update.js": "/js/main.bd918a21f99459ac0c5a.hot-update.js",
|
||||
"/js/main.cd35d127280aa3ed72bf.hot-update.js": "/js/main.cd35d127280aa3ed72bf.hot-update.js",
|
||||
"/js/main.fad01e38ba0a025fff8e.hot-update.js": "/js/main.fad01e38ba0a025fff8e.hot-update.js",
|
||||
"/js/main.5f401e8ed55572e305cb.hot-update.js": "/js/main.5f401e8ed55572e305cb.hot-update.js",
|
||||
"/js/main.0781bb19d4803f1c18cd.hot-update.js": "/js/main.0781bb19d4803f1c18cd.hot-update.js",
|
||||
"/js/main.4647329b218e437cd36f.hot-update.js": "/js/main.4647329b218e437cd36f.hot-update.js",
|
||||
"/js/main.cbadabd16ec66f6c56d6.hot-update.js": "/js/main.cbadabd16ec66f6c56d6.hot-update.js",
|
||||
"/js/main.2b9b5409dee799203a6c.hot-update.js": "/js/main.2b9b5409dee799203a6c.hot-update.js",
|
||||
"/js/main.21dd08ba11f996085687.hot-update.js": "/js/main.21dd08ba11f996085687.hot-update.js",
|
||||
"/js/main.afe5395def9a1c6bfba3.hot-update.js": "/js/main.afe5395def9a1c6bfba3.hot-update.js",
|
||||
"/js/main.bce3823ed3f28958fa5f.hot-update.js": "/js/main.bce3823ed3f28958fa5f.hot-update.js",
|
||||
"/js/main.6d0abf817c91fcbc246d.hot-update.js": "/js/main.6d0abf817c91fcbc246d.hot-update.js",
|
||||
"/js/main.d20577f503f0d098d7d3.hot-update.js": "/js/main.d20577f503f0d098d7d3.hot-update.js",
|
||||
"/js/main.609a2280828ed517bdc1.hot-update.js": "/js/main.609a2280828ed517bdc1.hot-update.js",
|
||||
"/js/main.d7ad5e9d5b97bbdc37db.hot-update.js": "/js/main.d7ad5e9d5b97bbdc37db.hot-update.js",
|
||||
"/js/main.66dc93a5bf413b7786be.hot-update.js": "/js/main.66dc93a5bf413b7786be.hot-update.js",
|
||||
"/js/main.e616a0e15889e0865a7b.hot-update.js": "/js/main.e616a0e15889e0865a7b.hot-update.js",
|
||||
"/js/main.58f7b99d0ee0f875e7dc.hot-update.js": "/js/main.58f7b99d0ee0f875e7dc.hot-update.js",
|
||||
"/js/main.e79958d0a6039bd1c735.hot-update.js": "/js/main.e79958d0a6039bd1c735.hot-update.js",
|
||||
"/js/main.f88db9bb087b351dc1a4.hot-update.js": "/js/main.f88db9bb087b351dc1a4.hot-update.js",
|
||||
"/js/main.8a872d714e919c2818ad.hot-update.js": "/js/main.8a872d714e919c2818ad.hot-update.js",
|
||||
"/js/main.8a719961322acc70e9ef.hot-update.js": "/js/main.8a719961322acc70e9ef.hot-update.js",
|
||||
"/js/main.a46e2e1d1032e2bb09ac.hot-update.js": "/js/main.a46e2e1d1032e2bb09ac.hot-update.js",
|
||||
"/js/main.f4e3d15c80b88b4936be.hot-update.js": "/js/main.f4e3d15c80b88b4936be.hot-update.js",
|
||||
"/js/main.afca50dd54922bf43026.hot-update.js": "/js/main.afca50dd54922bf43026.hot-update.js",
|
||||
"/js/main.22a33372319fe8c233e6.hot-update.js": "/js/main.22a33372319fe8c233e6.hot-update.js",
|
||||
"/js/main.066da2d957bdd49143d0.hot-update.js": "/js/main.066da2d957bdd49143d0.hot-update.js",
|
||||
"/js/main.1b2ebbdc84449535f397.hot-update.js": "/js/main.1b2ebbdc84449535f397.hot-update.js",
|
||||
"/js/main.4ac37a1720ab1578cec3.hot-update.js": "/js/main.4ac37a1720ab1578cec3.hot-update.js",
|
||||
"/js/main.623f3b31b7a87a8668b4.hot-update.js": "/js/main.623f3b31b7a87a8668b4.hot-update.js",
|
||||
"/js/main.7632e72183adc326096a.hot-update.js": "/js/main.7632e72183adc326096a.hot-update.js",
|
||||
"/js/main.6f007dc67a704a23e916.hot-update.js": "/js/main.6f007dc67a704a23e916.hot-update.js",
|
||||
"/js/main.e553af47e4049586ac44.hot-update.js": "/js/main.e553af47e4049586ac44.hot-update.js",
|
||||
"/js/main.92b31d53366c3ad8622b.hot-update.js": "/js/main.92b31d53366c3ad8622b.hot-update.js",
|
||||
"/js/main.e09827aea6d23ff07c1e.hot-update.js": "/js/main.e09827aea6d23ff07c1e.hot-update.js",
|
||||
"/js/main.04281820cee21428693e.hot-update.js": "/js/main.04281820cee21428693e.hot-update.js",
|
||||
"/js/main.f4067ec10e4cf8bd8a64.hot-update.js": "/js/main.f4067ec10e4cf8bd8a64.hot-update.js",
|
||||
"/js/main.430e98b75c1019f0292d.hot-update.js": "/js/main.430e98b75c1019f0292d.hot-update.js",
|
||||
"/js/main.578582fa836e0594b831.hot-update.js": "/js/main.578582fa836e0594b831.hot-update.js",
|
||||
"/js/main.0513b4f06058ecad6d0f.hot-update.js": "/js/main.0513b4f06058ecad6d0f.hot-update.js",
|
||||
"/js/main.311234d50f9c449dc26b.hot-update.js": "/js/main.311234d50f9c449dc26b.hot-update.js",
|
||||
"/js/main.aced0a5d0980fe602161.hot-update.js": "/js/main.aced0a5d0980fe602161.hot-update.js",
|
||||
"/js/main.ad0cab16daa356d285bc.hot-update.js": "/js/main.ad0cab16daa356d285bc.hot-update.js",
|
||||
"/js/main.40423454c85a1c529658.hot-update.js": "/js/main.40423454c85a1c529658.hot-update.js",
|
||||
"/js/main.5f56f327d2ee898c55f5.hot-update.js": "/js/main.5f56f327d2ee898c55f5.hot-update.js",
|
||||
"/js/main.d4206606dda50af813c6.hot-update.js": "/js/main.d4206606dda50af813c6.hot-update.js",
|
||||
"/js/main.b2fbfa55f560e77648b4.hot-update.js": "/js/main.b2fbfa55f560e77648b4.hot-update.js",
|
||||
"/js/main.e05f4750489ca893d94d.hot-update.js": "/js/main.e05f4750489ca893d94d.hot-update.js",
|
||||
"/js/main.af394e802253a7191c04.hot-update.js": "/js/main.af394e802253a7191c04.hot-update.js",
|
||||
"/js/main.ce416ea8ea898d2b842c.hot-update.js": "/js/main.ce416ea8ea898d2b842c.hot-update.js",
|
||||
"/js/main.c1b17e139a6bffd834f5.hot-update.js": "/js/main.c1b17e139a6bffd834f5.hot-update.js",
|
||||
"/js/main.46df392fd59c5498018f.hot-update.js": "/js/main.46df392fd59c5498018f.hot-update.js",
|
||||
"/js/main.5b083225fa62793303a5.hot-update.js": "/js/main.5b083225fa62793303a5.hot-update.js",
|
||||
"/js/main.ff1635f87e05dae40c64.hot-update.js": "/js/main.ff1635f87e05dae40c64.hot-update.js",
|
||||
"/js/main.181ca1486b6c63df043a.hot-update.js": "/js/main.181ca1486b6c63df043a.hot-update.js",
|
||||
"/js/main.aed85b7900a1ffb09898.hot-update.js": "/js/main.aed85b7900a1ffb09898.hot-update.js",
|
||||
"/js/main.a96f14da0f826e0f73fe.hot-update.js": "/js/main.a96f14da0f826e0f73fe.hot-update.js",
|
||||
"/js/main.19bc16cb52d3dc751604.hot-update.js": "/js/main.19bc16cb52d3dc751604.hot-update.js",
|
||||
"/js/main.13103769e6134409fa2a.hot-update.js": "/js/main.13103769e6134409fa2a.hot-update.js",
|
||||
"/js/main.a8ddc0df618dca5b1160.hot-update.js": "/js/main.a8ddc0df618dca5b1160.hot-update.js",
|
||||
"/js/main.98abd09248c9893c4a30.hot-update.js": "/js/main.98abd09248c9893c4a30.hot-update.js",
|
||||
"/js/main.4b42b13afb3e6e18a916.hot-update.js": "/js/main.4b42b13afb3e6e18a916.hot-update.js",
|
||||
"/js/main.da8ab6e69627bbcff9a1.hot-update.js": "/js/main.da8ab6e69627bbcff9a1.hot-update.js",
|
||||
"/js/main.fb5fe1c0ead4cb6c3647.hot-update.js": "/js/main.fb5fe1c0ead4cb6c3647.hot-update.js",
|
||||
"/js/main.ecbde6764e0032ecaaff.hot-update.js": "/js/main.ecbde6764e0032ecaaff.hot-update.js",
|
||||
"/js/main.45cdddc1e11584321f8f.hot-update.js": "/js/main.45cdddc1e11584321f8f.hot-update.js",
|
||||
"/js/main.5e716c4399d6c4e7c60c.hot-update.js": "/js/main.5e716c4399d6c4e7c60c.hot-update.js",
|
||||
"/js/main.85b156a9d0ebbe510f72.hot-update.js": "/js/main.85b156a9d0ebbe510f72.hot-update.js",
|
||||
"/js/main.5de3358896db4e70d82d.hot-update.js": "/js/main.5de3358896db4e70d82d.hot-update.js",
|
||||
"/js/main.ede66032dd422936528c.hot-update.js": "/js/main.ede66032dd422936528c.hot-update.js",
|
||||
"/js/main.5465d00f698d022075f8.hot-update.js": "/js/main.5465d00f698d022075f8.hot-update.js",
|
||||
"/js/main.aa025d5f6feec8c0dab2.hot-update.js": "/js/main.aa025d5f6feec8c0dab2.hot-update.js",
|
||||
"/js/main.820910b8cdce9f354543.hot-update.js": "/js/main.820910b8cdce9f354543.hot-update.js",
|
||||
"/js/main.d14ee47779985cb32ec0.hot-update.js": "/js/main.d14ee47779985cb32ec0.hot-update.js",
|
||||
"/js/main.8d266a1d740fa389c2bf.hot-update.js": "/js/main.8d266a1d740fa389c2bf.hot-update.js",
|
||||
"/js/main.99143ecd6bfafab9b677.hot-update.js": "/js/main.99143ecd6bfafab9b677.hot-update.js",
|
||||
"/js/main.bbb2be0d78aaec9dfda1.hot-update.js": "/js/main.bbb2be0d78aaec9dfda1.hot-update.js",
|
||||
"/js/main.76904835fe400dd9848f.hot-update.js": "/js/main.76904835fe400dd9848f.hot-update.js",
|
||||
"/js/main.cafd83e6c2744baad34a.hot-update.js": "/js/main.cafd83e6c2744baad34a.hot-update.js",
|
||||
"/js/main.2002a76681e8d0433941.hot-update.js": "/js/main.2002a76681e8d0433941.hot-update.js",
|
||||
"/js/main.2fd100a299a791164337.hot-update.js": "/js/main.2fd100a299a791164337.hot-update.js",
|
||||
"/js/main.3abd3c2a19f02f47bebc.hot-update.js": "/js/main.3abd3c2a19f02f47bebc.hot-update.js",
|
||||
"/js/main.2bc80b9424efd6eadbed.hot-update.js": "/js/main.2bc80b9424efd6eadbed.hot-update.js",
|
||||
"/js/main.48a8f2b34315a51837ed.hot-update.js": "/js/main.48a8f2b34315a51837ed.hot-update.js",
|
||||
"/js/main.bb7c8231d66a0cb23884.hot-update.js": "/js/main.bb7c8231d66a0cb23884.hot-update.js",
|
||||
"/js/main.f3c27d8639d237140393.hot-update.js": "/js/main.f3c27d8639d237140393.hot-update.js",
|
||||
"/js/main.aa88aa732da3530ef6fc.hot-update.js": "/js/main.aa88aa732da3530ef6fc.hot-update.js",
|
||||
"/js/main.2f10611b4cb0849baf9a.hot-update.js": "/js/main.2f10611b4cb0849baf9a.hot-update.js",
|
||||
"/js/main.cdb3c9099ecd3aef1c6d.hot-update.js": "/js/main.cdb3c9099ecd3aef1c6d.hot-update.js",
|
||||
"/js/main.4f6cbd01f21463974339.hot-update.js": "/js/main.4f6cbd01f21463974339.hot-update.js",
|
||||
"/js/main.75e920f256de199321da.hot-update.js": "/js/main.75e920f256de199321da.hot-update.js",
|
||||
"/js/main.3aa153417b65e9dd8e66.hot-update.js": "/js/main.3aa153417b65e9dd8e66.hot-update.js",
|
||||
"/js/main.412dd1fb982791c51e22.hot-update.js": "/js/main.412dd1fb982791c51e22.hot-update.js",
|
||||
"/js/main.f7dace814dd7cf6cd2d2.hot-update.js": "/js/main.f7dace814dd7cf6cd2d2.hot-update.js",
|
||||
"/js/main.107c49051b193edea885.hot-update.js": "/js/main.107c49051b193edea885.hot-update.js",
|
||||
"/js/main.b31481977f618806d60a.hot-update.js": "/js/main.b31481977f618806d60a.hot-update.js",
|
||||
"/js/main.44dcaa7eb8423dcba8c0.hot-update.js": "/js/main.44dcaa7eb8423dcba8c0.hot-update.js",
|
||||
"/js/main.ff751f6b0426846af09f.hot-update.js": "/js/main.ff751f6b0426846af09f.hot-update.js",
|
||||
"/js/main.2b668837a746a960d470.hot-update.js": "/js/main.2b668837a746a960d470.hot-update.js",
|
||||
"/js/main.c26ae7faad32e3f752f9.hot-update.js": "/js/main.c26ae7faad32e3f752f9.hot-update.js",
|
||||
"/js/main.71819bd2c52cfd992c49.hot-update.js": "/js/main.71819bd2c52cfd992c49.hot-update.js",
|
||||
"/js/main.b2a492cb77c7a3dbc8b8.hot-update.js": "/js/main.b2a492cb77c7a3dbc8b8.hot-update.js",
|
||||
"/js/main.755b3b6f634d7ea41269.hot-update.js": "/js/main.755b3b6f634d7ea41269.hot-update.js",
|
||||
"/js/main.63a686c9457eecec0aed.hot-update.js": "/js/main.63a686c9457eecec0aed.hot-update.js",
|
||||
"/js/main.bc7270bc738d06bf003c.hot-update.js": "/js/main.bc7270bc738d06bf003c.hot-update.js",
|
||||
"/js/main.6a812e6a9a8fdec9e0f9.hot-update.js": "/js/main.6a812e6a9a8fdec9e0f9.hot-update.js",
|
||||
"/js/main.605b505026463b82cf92.hot-update.js": "/js/main.605b505026463b82cf92.hot-update.js",
|
||||
"/js/main.67ec3e67dc7fe249a511.hot-update.js": "/js/main.67ec3e67dc7fe249a511.hot-update.js",
|
||||
"/js/main.60f7f14041f1b1c43ba7.hot-update.js": "/js/main.60f7f14041f1b1c43ba7.hot-update.js",
|
||||
"/js/main.378fefdc90168f530ced.hot-update.js": "/js/main.378fefdc90168f530ced.hot-update.js",
|
||||
"/js/main.50bcdbbb6689ab1f3ff8.hot-update.js": "/js/main.50bcdbbb6689ab1f3ff8.hot-update.js",
|
||||
"/js/main.bad32b198b2701141385.hot-update.js": "/js/main.bad32b198b2701141385.hot-update.js",
|
||||
"/js/main.054d269f4a98578503c1.hot-update.js": "/js/main.054d269f4a98578503c1.hot-update.js",
|
||||
"/js/main.41b69188f146b379f87b.hot-update.js": "/js/main.41b69188f146b379f87b.hot-update.js",
|
||||
"/js/main.3e018a3648dfc61d3df3.hot-update.js": "/js/main.3e018a3648dfc61d3df3.hot-update.js",
|
||||
"/js/main.2936652ac5660f94a796.hot-update.js": "/js/main.2936652ac5660f94a796.hot-update.js",
|
||||
"/js/main.fcc623fc42f160e06cfe.hot-update.js": "/js/main.fcc623fc42f160e06cfe.hot-update.js",
|
||||
"/js/main.93d580e0883dc95e1116.hot-update.js": "/js/main.93d580e0883dc95e1116.hot-update.js",
|
||||
"/js/main.28d29c71ea1ed0a0b0b4.hot-update.js": "/js/main.28d29c71ea1ed0a0b0b4.hot-update.js",
|
||||
"/js/main.2a76ff437524f4ee71c0.hot-update.js": "/js/main.2a76ff437524f4ee71c0.hot-update.js",
|
||||
"/js/main.cff525ce21d6a17180c1.hot-update.js": "/js/main.cff525ce21d6a17180c1.hot-update.js",
|
||||
"/js/main.160476920d84b7b64f03.hot-update.js": "/js/main.160476920d84b7b64f03.hot-update.js",
|
||||
"/js/main.30dda3674a213af39664.hot-update.js": "/js/main.30dda3674a213af39664.hot-update.js",
|
||||
"/js/main.c011a2db86676be81958.hot-update.js": "/js/main.c011a2db86676be81958.hot-update.js",
|
||||
"/js/main.3b1eb2be045aeb2794d7.hot-update.js": "/js/main.3b1eb2be045aeb2794d7.hot-update.js",
|
||||
"/js/main.06a1a0a0d13e736f4b21.hot-update.js": "/js/main.06a1a0a0d13e736f4b21.hot-update.js",
|
||||
"/js/main.e01d5781e9a5c7916665.hot-update.js": "/js/main.e01d5781e9a5c7916665.hot-update.js",
|
||||
"/js/main.a8be6a86ef7ea1fa09aa.hot-update.js": "/js/main.a8be6a86ef7ea1fa09aa.hot-update.js",
|
||||
"/js/main.10ef93f11f9971bffcd0.hot-update.js": "/js/main.10ef93f11f9971bffcd0.hot-update.js",
|
||||
"/js/main.8272060c881465e5c1b8.hot-update.js": "/js/main.8272060c881465e5c1b8.hot-update.js",
|
||||
"/js/main.3c4afd1bbc5dbddbc2f5.hot-update.js": "/js/main.3c4afd1bbc5dbddbc2f5.hot-update.js",
|
||||
"/js/main.5095c746248692e2fab9.hot-update.js": "/js/main.5095c746248692e2fab9.hot-update.js",
|
||||
"/js/main.b7e058950b6450f5be86.hot-update.js": "/js/main.b7e058950b6450f5be86.hot-update.js",
|
||||
"/js/main.0cd416bcfc7be3e736b4.hot-update.js": "/js/main.0cd416bcfc7be3e736b4.hot-update.js",
|
||||
"/js/main.074d97f29afb98992021.hot-update.js": "/js/main.074d97f29afb98992021.hot-update.js",
|
||||
"/js/main.b832de402f7a0bb84f16.hot-update.js": "/js/main.b832de402f7a0bb84f16.hot-update.js",
|
||||
"/js/main.e2acc484ee30d5bc511b.hot-update.js": "/js/main.e2acc484ee30d5bc511b.hot-update.js",
|
||||
"/js/main.6062f643e9e4b8ca338f.hot-update.js": "/js/main.6062f643e9e4b8ca338f.hot-update.js",
|
||||
"/js/main.2e9db006c2bd6ed06276.hot-update.js": "/js/main.2e9db006c2bd6ed06276.hot-update.js",
|
||||
"/js/main.c5440e1711c2366531e8.hot-update.js": "/js/main.c5440e1711c2366531e8.hot-update.js",
|
||||
"/js/main.9621c2052cd66aab368f.hot-update.js": "/js/main.9621c2052cd66aab368f.hot-update.js",
|
||||
"/js/main.0fe5939166b86f760041.hot-update.js": "/js/main.0fe5939166b86f760041.hot-update.js",
|
||||
"/js/main.9a08a8a2109d7993ea97.hot-update.js": "/js/main.9a08a8a2109d7993ea97.hot-update.js",
|
||||
"/js/main.bf10e2245b146a2cf6c0.hot-update.js": "/js/main.bf10e2245b146a2cf6c0.hot-update.js",
|
||||
"/js/main.9c0628dcaf454d8ef45e.hot-update.js": "/js/main.9c0628dcaf454d8ef45e.hot-update.js",
|
||||
"/js/main.93b39c613c426756176e.hot-update.js": "/js/main.93b39c613c426756176e.hot-update.js",
|
||||
"/js/main.cddfc9fafcd6885f21e7.hot-update.js": "/js/main.cddfc9fafcd6885f21e7.hot-update.js",
|
||||
"/js/main.cca75105094aa748a70d.hot-update.js": "/js/main.cca75105094aa748a70d.hot-update.js",
|
||||
"/js/main.c8c27998c2b3cf45a66b.hot-update.js": "/js/main.c8c27998c2b3cf45a66b.hot-update.js",
|
||||
"/js/main.329fc90f8bb0ac52ca61.hot-update.js": "/js/main.329fc90f8bb0ac52ca61.hot-update.js",
|
||||
"/js/main.6f31b38bb7c9668fbbce.hot-update.js": "/js/main.6f31b38bb7c9668fbbce.hot-update.js",
|
||||
"/js/main.1fd945801f700932880d.hot-update.js": "/js/main.1fd945801f700932880d.hot-update.js",
|
||||
"/js/main.d4f2e81b634d134be133.hot-update.js": "/js/main.d4f2e81b634d134be133.hot-update.js",
|
||||
"/js/main.b80e30c83de500fc196d.hot-update.js": "/js/main.b80e30c83de500fc196d.hot-update.js",
|
||||
"/js/main.8d8063569f01acb69bc7.hot-update.js": "/js/main.8d8063569f01acb69bc7.hot-update.js",
|
||||
"/js/main.d4d7a8a2373540a95962.hot-update.js": "/js/main.d4d7a8a2373540a95962.hot-update.js",
|
||||
"/js/main.4b0768ce7a19f5093747.hot-update.js": "/js/main.4b0768ce7a19f5093747.hot-update.js",
|
||||
"/js/main.34079aa9b29123a2083c.hot-update.js": "/js/main.34079aa9b29123a2083c.hot-update.js",
|
||||
"/js/main.ec6c429db76fb2dd0212.hot-update.js": "/js/main.ec6c429db76fb2dd0212.hot-update.js",
|
||||
"/js/main.2ab0c9706b0b5f27748f.hot-update.js": "/js/main.2ab0c9706b0b5f27748f.hot-update.js",
|
||||
"/js/main.01b547932ef0a411f639.hot-update.js": "/js/main.01b547932ef0a411f639.hot-update.js",
|
||||
"/js/main.f9d0e38a0c8267727c41.hot-update.js": "/js/main.f9d0e38a0c8267727c41.hot-update.js",
|
||||
"/js/main.47a584d9a6bfa1cbaca6.hot-update.js": "/js/main.47a584d9a6bfa1cbaca6.hot-update.js",
|
||||
"/js/main.a891f426506bbc45d3f6.hot-update.js": "/js/main.a891f426506bbc45d3f6.hot-update.js",
|
||||
"/js/main.0ab4b48148074ad23aec.hot-update.js": "/js/main.0ab4b48148074ad23aec.hot-update.js",
|
||||
"/js/main.d851fe54d559c0c439d4.hot-update.js": "/js/main.d851fe54d559c0c439d4.hot-update.js",
|
||||
"/js/main.965fc731cb2a00fcde50.hot-update.js": "/js/main.965fc731cb2a00fcde50.hot-update.js",
|
||||
"/js/main.7efc63569bd16d43be96.hot-update.js": "/js/main.7efc63569bd16d43be96.hot-update.js",
|
||||
"/js/main.b56f81dd7b7cf2b4a9b2.hot-update.js": "/js/main.b56f81dd7b7cf2b4a9b2.hot-update.js",
|
||||
"/js/main.6b538f47d7084fc5c056.hot-update.js": "/js/main.6b538f47d7084fc5c056.hot-update.js",
|
||||
"/js/main.0847c2f8c76446ffc1e1.hot-update.js": "/js/main.0847c2f8c76446ffc1e1.hot-update.js",
|
||||
"/js/main.fa9ded0194e51af751b4.hot-update.js": "/js/main.fa9ded0194e51af751b4.hot-update.js",
|
||||
"/js/main.8e479c4cc567a7f86fbf.hot-update.js": "/js/main.8e479c4cc567a7f86fbf.hot-update.js",
|
||||
"/js/main.c2131ca9020d74887a86.hot-update.js": "/js/main.c2131ca9020d74887a86.hot-update.js",
|
||||
"/js/main.ae7a03f5a01e1b1fb79f.hot-update.js": "/js/main.ae7a03f5a01e1b1fb79f.hot-update.js",
|
||||
"/js/main.4719a377f8009f031b35.hot-update.js": "/js/main.4719a377f8009f031b35.hot-update.js",
|
||||
"/js/main.c87c48fa6a02b2403911.hot-update.js": "/js/main.c87c48fa6a02b2403911.hot-update.js",
|
||||
"/js/main.47109b08d1688186ca0f.hot-update.js": "/js/main.47109b08d1688186ca0f.hot-update.js",
|
||||
"/js/main.74b35f583dd235319010.hot-update.js": "/js/main.74b35f583dd235319010.hot-update.js",
|
||||
"/js/main.8ad646c7fdf758fc3077.hot-update.js": "/js/main.8ad646c7fdf758fc3077.hot-update.js",
|
||||
"/js/main.f43a2d4521fab4b9a94e.hot-update.js": "/js/main.f43a2d4521fab4b9a94e.hot-update.js",
|
||||
"/js/main.3435832fdb3175879cf7.hot-update.js": "/js/main.3435832fdb3175879cf7.hot-update.js",
|
||||
"/js/main.c58b3c90adbd372bdd97.hot-update.js": "/js/main.c58b3c90adbd372bdd97.hot-update.js",
|
||||
"/js/main.c08fa8f3335ed51d3f75.hot-update.js": "/js/main.c08fa8f3335ed51d3f75.hot-update.js",
|
||||
"/js/main.4c82e15c2d67b287e8f8.hot-update.js": "/js/main.4c82e15c2d67b287e8f8.hot-update.js",
|
||||
"/js/main.508fada0c3ecbb174a11.hot-update.js": "/js/main.508fada0c3ecbb174a11.hot-update.js",
|
||||
"/js/main.61da2361919afdd32838.hot-update.js": "/js/main.61da2361919afdd32838.hot-update.js",
|
||||
"/js/main.602057bf75bb7533497a.hot-update.js": "/js/main.602057bf75bb7533497a.hot-update.js",
|
||||
"/js/main.08f17d3db95a580ebcff.hot-update.js": "/js/main.08f17d3db95a580ebcff.hot-update.js",
|
||||
"/js/main.fde740604ac11217991e.hot-update.js": "/js/main.fde740604ac11217991e.hot-update.js",
|
||||
"/js/main.470a4e47222c5cd0ca6c.hot-update.js": "/js/main.470a4e47222c5cd0ca6c.hot-update.js",
|
||||
"/js/main.78a6535c7174d7490de2.hot-update.js": "/js/main.78a6535c7174d7490de2.hot-update.js",
|
||||
"/js/main.c8a4f8f465ce6970b2ea.hot-update.js": "/js/main.c8a4f8f465ce6970b2ea.hot-update.js",
|
||||
"/js/main.d8e90a128296036c0c15.hot-update.js": "/js/main.d8e90a128296036c0c15.hot-update.js",
|
||||
"/js/main.4f84cab5a93c6fca138b.hot-update.js": "/js/main.4f84cab5a93c6fca138b.hot-update.js",
|
||||
"/js/main.ff08fabb70c77845dacf.hot-update.js": "/js/main.ff08fabb70c77845dacf.hot-update.js",
|
||||
"/js/main.73b58a7269460f4044f6.hot-update.js": "/js/main.73b58a7269460f4044f6.hot-update.js",
|
||||
"/js/main.bffdfdca5226e1971a1f.hot-update.js": "/js/main.bffdfdca5226e1971a1f.hot-update.js",
|
||||
"/js/main.5d24f494cb656c4aea06.hot-update.js": "/js/main.5d24f494cb656c4aea06.hot-update.js",
|
||||
"/js/main.284dea61b9e166ccf9f0.hot-update.js": "/js/main.284dea61b9e166ccf9f0.hot-update.js",
|
||||
"/js/main.0865fc8f9bcc9f534bd5.hot-update.js": "/js/main.0865fc8f9bcc9f534bd5.hot-update.js",
|
||||
"/js/main.6d388afa93af449e99fd.hot-update.js": "/js/main.6d388afa93af449e99fd.hot-update.js",
|
||||
"/js/main.108d51ae66a3b2e72dbc.hot-update.js": "/js/main.108d51ae66a3b2e72dbc.hot-update.js",
|
||||
"/js/main.f78ad0c36590167303c7.hot-update.js": "/js/main.f78ad0c36590167303c7.hot-update.js",
|
||||
"/js/main.607a892f908136301269.hot-update.js": "/js/main.607a892f908136301269.hot-update.js",
|
||||
"/js/main.85d4f345841dfbb40e07.hot-update.js": "/js/main.85d4f345841dfbb40e07.hot-update.js",
|
||||
"/js/main.945083b1b0445126d561.hot-update.js": "/js/main.945083b1b0445126d561.hot-update.js",
|
||||
"/js/main.b09684c47f389bcc887e.hot-update.js": "/js/main.b09684c47f389bcc887e.hot-update.js",
|
||||
"/js/main.19d37869465800d743bb.hot-update.js": "/js/main.19d37869465800d743bb.hot-update.js",
|
||||
"/js/main.c54cd5dfd83b055f78af.hot-update.js": "/js/main.c54cd5dfd83b055f78af.hot-update.js",
|
||||
"/js/main.672249e68aa26cdc3467.hot-update.js": "/js/main.672249e68aa26cdc3467.hot-update.js",
|
||||
"/js/main.784cd47e7b5a14f729ac.hot-update.js": "/js/main.784cd47e7b5a14f729ac.hot-update.js",
|
||||
"/js/main.6bb6b81e129e23fb017c.hot-update.js": "/js/main.6bb6b81e129e23fb017c.hot-update.js",
|
||||
"/js/main.db67acf9cd2003665508.hot-update.js": "/js/main.db67acf9cd2003665508.hot-update.js",
|
||||
"/js/main.42bbb785d8bc3374175e.hot-update.js": "/js/main.42bbb785d8bc3374175e.hot-update.js",
|
||||
"/js/main.0985aa644d053b57a808.hot-update.js": "/js/main.0985aa644d053b57a808.hot-update.js",
|
||||
"/js/main.49338628cefc585d505e.hot-update.js": "/js/main.49338628cefc585d505e.hot-update.js",
|
||||
"/js/main.efce52309183dd157590.hot-update.js": "/js/main.efce52309183dd157590.hot-update.js",
|
||||
"/js/main.35aeb37a9609024aeac9.hot-update.js": "/js/main.35aeb37a9609024aeac9.hot-update.js",
|
||||
"/js/main.53a1fde399bfc98f701c.hot-update.js": "/js/main.53a1fde399bfc98f701c.hot-update.js",
|
||||
"/js/main.f822941031e6e082f07c.hot-update.js": "/js/main.f822941031e6e082f07c.hot-update.js",
|
||||
"/js/main.ca79ce64147b6e0e55cb.hot-update.js": "/js/main.ca79ce64147b6e0e55cb.hot-update.js",
|
||||
"/js/main.937e0ee30a05573041b3.hot-update.js": "/js/main.937e0ee30a05573041b3.hot-update.js",
|
||||
"/js/main.e7d9b3bc53ac4b3053bc.hot-update.js": "/js/main.e7d9b3bc53ac4b3053bc.hot-update.js",
|
||||
"/js/main.96bcd5ef0412bc46d1ed.hot-update.js": "/js/main.96bcd5ef0412bc46d1ed.hot-update.js",
|
||||
"/js/main.b07bbcaf5c0f638640a0.hot-update.js": "/js/main.b07bbcaf5c0f638640a0.hot-update.js",
|
||||
"/js/main.25e093e405cc4a690242.hot-update.js": "/js/main.25e093e405cc4a690242.hot-update.js",
|
||||
"/js/main.6e0fa93bb2ee5213af77.hot-update.js": "/js/main.6e0fa93bb2ee5213af77.hot-update.js",
|
||||
"/js/main.ef2172323fe57a1a3c55.hot-update.js": "/js/main.ef2172323fe57a1a3c55.hot-update.js",
|
||||
"/js/main.91c8655cf52d84f6a284.hot-update.js": "/js/main.91c8655cf52d84f6a284.hot-update.js",
|
||||
"/js/main.8864391e1b0b56720f7c.hot-update.js": "/js/main.8864391e1b0b56720f7c.hot-update.js",
|
||||
"/js/main.bdb661bd0667afb07d42.hot-update.js": "/js/main.bdb661bd0667afb07d42.hot-update.js",
|
||||
"/js/main.a907b2a57b6a2917f3da.hot-update.js": "/js/main.a907b2a57b6a2917f3da.hot-update.js",
|
||||
"/js/main.8bd891d1410908be3f0b.hot-update.js": "/js/main.8bd891d1410908be3f0b.hot-update.js",
|
||||
"/js/main.70b0ed0c55368738458d.hot-update.js": "/js/main.70b0ed0c55368738458d.hot-update.js",
|
||||
"/js/main.0c542c7f0c6e83b4fa18.hot-update.js": "/js/main.0c542c7f0c6e83b4fa18.hot-update.js",
|
||||
"/js/main.69f8ec453d307c1f58d5.hot-update.js": "/js/main.69f8ec453d307c1f58d5.hot-update.js",
|
||||
"/js/main.3b0d20392d7731b198b2.hot-update.js": "/js/main.3b0d20392d7731b198b2.hot-update.js",
|
||||
"/js/main.9755e76f416f1eb7566c.hot-update.js": "/js/main.9755e76f416f1eb7566c.hot-update.js",
|
||||
"/js/main.8fd8b140290b7b62e8bf.hot-update.js": "/js/main.8fd8b140290b7b62e8bf.hot-update.js",
|
||||
"/js/main.a61786216f1a7f65d8c4.hot-update.js": "/js/main.a61786216f1a7f65d8c4.hot-update.js",
|
||||
"/js/main.ab0a2ac4fee47195d276.hot-update.js": "/js/main.ab0a2ac4fee47195d276.hot-update.js",
|
||||
"/js/main.ea5986d9d962e977f388.hot-update.js": "/js/main.ea5986d9d962e977f388.hot-update.js",
|
||||
"/js/main.e9ecf936319bd5e5a9ba.hot-update.js": "/js/main.e9ecf936319bd5e5a9ba.hot-update.js",
|
||||
"/js/main.83747ba398461b3dae0c.hot-update.js": "/js/main.83747ba398461b3dae0c.hot-update.js"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
<MobileNavigation />
|
||||
|
||||
<!--Confirm Popup-->
|
||||
<Confirm />
|
||||
|
||||
<!--Share Item setup-->
|
||||
<ShareCreate/>
|
||||
<ShareEdit/>
|
||||
@@ -42,6 +45,7 @@
|
||||
import MobileNavigation from '@/components/Others/MobileNavigation'
|
||||
import MobileMenu from '@/components/FilesView/MobileMenu'
|
||||
import ShareCreate from '@/components/Others/ShareCreate'
|
||||
import Confirm from '@/components/Others/Popup/Confirm'
|
||||
import ShareEdit from '@/components/Others/ShareEdit'
|
||||
import MoveItem from '@/components/Others/MoveItem'
|
||||
import Vignette from '@/components/Others/Vignette'
|
||||
@@ -61,6 +65,7 @@
|
||||
ShareEdit,
|
||||
MoveItem,
|
||||
Vignette,
|
||||
Confirm,
|
||||
MenuBar,
|
||||
Alert,
|
||||
},
|
||||
|
||||
@@ -136,6 +136,7 @@
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
|
||||
.title {
|
||||
@include font-size(22);
|
||||
text-transform: uppercase;
|
||||
|
||||
@@ -110,7 +110,8 @@
|
||||
'homeDirectory',
|
||||
]),
|
||||
hasCapacity() {
|
||||
return this.$store.getters.user.relationships.storage.data.attributes.used <= 100
|
||||
//return this.$store.getters.user.relationships.storage.data.attributes.used <= 100
|
||||
return true
|
||||
},
|
||||
directoryName() {
|
||||
return this.currentFolder ? this.currentFolder.name : this.homeDirectory.name
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
color: $theme;
|
||||
background: rgba($theme, 0.1);
|
||||
}
|
||||
|
||||
&.red {
|
||||
color: $danger;
|
||||
background: rgba($danger, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
<template>
|
||||
<div class="page-tab">
|
||||
<slot></slot>
|
||||
<div id="loader" v-if="isLoading">
|
||||
<Spinner></Spinner>
|
||||
</div>
|
||||
<slot v-if="! isLoading"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
|
||||
export default {
|
||||
name: 'PageTab',
|
||||
props: ['isLoading'],
|
||||
components: {
|
||||
Spinner,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</section>
|
||||
<footer class="plan-footer">
|
||||
<b class="price">
|
||||
{{ plan.data.attributes.price }} USD/Mo.
|
||||
{{ plan.data.attributes.price }}/Mo.
|
||||
</b>
|
||||
<ButtonBase @click.native="selectPlan(plan)" type="submit" button-style="secondary" class="sign-in-button">
|
||||
Sign Up
|
||||
@@ -52,12 +52,7 @@
|
||||
|
||||
axios.get('/api/public/pricing')
|
||||
.then(response => {
|
||||
this.plans = response.data.data.filter(plan => {
|
||||
if (this.$store.getters.user.relationships.subscription)
|
||||
return plan.data.attributes.capacity > this.$store.getters.user.relationships.subscription.data.attributes.capacity
|
||||
|
||||
return true
|
||||
})
|
||||
this.plans = response.data
|
||||
this.$emit('load', false)
|
||||
})
|
||||
}
|
||||
@@ -72,6 +67,7 @@
|
||||
text-align: center;
|
||||
flex: 0 0 33%;
|
||||
padding: 0 25px;
|
||||
margin-bottom: 45px;
|
||||
|
||||
.plan-wrapper {
|
||||
box-shadow: 0 7px 20px 5px hsla(220, 36%, 16%, 0.03);
|
||||
|
||||
133
resources/js/components/Others/Popup/Confirm.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<PopupWrapper>
|
||||
|
||||
<div class="popup-image">
|
||||
<span class="emoji">{{ emoji }}</span>
|
||||
</div>
|
||||
|
||||
<PopupContent class="content">
|
||||
<h1 v-if="title" class="title">{{ title }}</h1>
|
||||
<p v-if="message" class="message">{{ message }}</p>
|
||||
</PopupContent>
|
||||
|
||||
<PopupActions>
|
||||
<ButtonBase
|
||||
@click.native="closePopup"
|
||||
button-style="secondary"
|
||||
class="popup-button"
|
||||
>Cancel
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
@click.native="confirm"
|
||||
:button-style="buttonColor"
|
||||
class="popup-button"
|
||||
>Yes, I'm sure
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
</PopupWrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PopupWrapper from '@/components/Others/Popup/PopupWrapper'
|
||||
import PopupActions from '@/components/Others/Popup/PopupActions'
|
||||
import PopupContent from '@/components/Others/Popup/PopupContent'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'ConfirmPopup',
|
||||
components: {
|
||||
PopupWrapper,
|
||||
PopupActions,
|
||||
PopupContent,
|
||||
ButtonBase,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
confirmationData: [],
|
||||
message: undefined,
|
||||
title: undefined,
|
||||
emoji: undefined,
|
||||
buttonColor: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closePopup() {
|
||||
events.$emit('popup:close')
|
||||
},
|
||||
confirm() {
|
||||
// Close popup
|
||||
events.$emit('popup:close')
|
||||
|
||||
// Confirmation popup
|
||||
events.$emit('action:confirmed', this.confirmationData)
|
||||
|
||||
// Clear confirmation data
|
||||
this.confirmationData = []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// Show confirm
|
||||
events.$on('confirm:open', args => {
|
||||
this.title = args.title
|
||||
this.message = args.message
|
||||
this.emoji = '🤔'
|
||||
this.confirmationData = args.action
|
||||
this.buttonColor = 'danger-solid'
|
||||
|
||||
if (args.buttonColor) {
|
||||
this.buttonColor = args.buttonColor
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.popup-image {
|
||||
padding-top: 20px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.emoji {
|
||||
@include font-size(56);
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
|
||||
.title {
|
||||
@include font-size(22);
|
||||
text-transform: uppercase;
|
||||
font-weight: 800;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.message {
|
||||
@include font-size(16);
|
||||
color: #333;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.content {
|
||||
.title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.message {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -35,6 +35,13 @@
|
||||
this.isVisibleWrapper = true
|
||||
})
|
||||
|
||||
// Open called popup
|
||||
events.$on('confirm:open', ({name}) => {
|
||||
|
||||
if (this.name === name)
|
||||
this.isVisibleWrapper = true
|
||||
})
|
||||
|
||||
// Close popup
|
||||
events.$on('popup:close', () => {
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
events.$on('popup:open', () => this.isVisibleVignette = true)
|
||||
events.$on('alert:open', () => this.isVisibleVignette = true)
|
||||
events.$on('success:open', () => this.isVisibleVignette = true)
|
||||
events.$on('confirm:open', () => this.isVisibleVignette = true)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
584
resources/js/helpers.js
vendored
@@ -5,313 +5,285 @@ import axios from 'axios'
|
||||
import router from '@/router'
|
||||
|
||||
const Helpers = {
|
||||
install(Vue) {
|
||||
|
||||
Vue.prototype.$updateText = debounce(function (route, name, value) {
|
||||
|
||||
if (value === '') return
|
||||
|
||||
axios.patch(this.$store.getters.api + route, {name, value})
|
||||
.catch(error => {
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
})
|
||||
}, 300)
|
||||
|
||||
Vue.prototype.$updateImage = function (route, name, image) {
|
||||
|
||||
// Create form
|
||||
let formData = new FormData()
|
||||
|
||||
// Add image to form
|
||||
formData.append(name, image)
|
||||
formData.append('_method', 'PATCH')
|
||||
|
||||
axios.post(this.$store.getters.api + route, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Vue.prototype.$openImageOnNewTab = function(source) {
|
||||
let win = window.open(source, '_blank')
|
||||
|
||||
win.focus()
|
||||
}
|
||||
|
||||
Vue.prototype.$createFolder = function(folderName) {
|
||||
this.$store.dispatch('createFolder', folderName)
|
||||
}
|
||||
|
||||
Vue.prototype.$uploadFiles = async function(files) {
|
||||
// Prevent submit empty files
|
||||
if (files && files.length == 0) return
|
||||
|
||||
// Check storage size
|
||||
if (! this.$isThisLocation(['public']) && this.$store.getters.app.storage.percentage >= 100) {
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😬😬😬',
|
||||
title: this.$t('popup_exceed_limit.title'),
|
||||
message: this.$t('popup_exceed_limit.message')
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let fileCount = files ? files.length : 0
|
||||
let fileCountSucceed = 1
|
||||
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: fileCount
|
||||
})
|
||||
|
||||
// Get parent id
|
||||
const rootFolder = this.$store.getters.currentFolder
|
||||
? this.$store.getters.currentFolder.unique_id
|
||||
: 0
|
||||
|
||||
for (var i = files.length - 1; i >= 0; i--) {
|
||||
let formData = new FormData()
|
||||
|
||||
// Append data
|
||||
formData.append('file', files[i])
|
||||
|
||||
// Append form data
|
||||
formData.append('parent_id', rootFolder)
|
||||
|
||||
console.log(i);
|
||||
console.log(files[i]);
|
||||
console.log(formData);
|
||||
|
||||
// Upload data
|
||||
await store.dispatch('uploadFiles', formData)
|
||||
.then(() => {
|
||||
// Progress file log
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: fileCount
|
||||
})
|
||||
|
||||
// Uploading finished
|
||||
if (fileCount === fileCountSucceed) {
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
|
||||
} else {
|
||||
// Add uploaded file
|
||||
fileCountSucceed++
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
if (error.response.status === 423) {
|
||||
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😬😬😬',
|
||||
title: this.$t('popup_exceed_limit.title'),
|
||||
message: this.$t('popup_exceed_limit.message')
|
||||
})
|
||||
|
||||
} else if (error.response.status === 413) {
|
||||
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😟',
|
||||
title: this.$t('popup_paylod_error.title'),
|
||||
message: this.$t('popup_paylod_error.message')
|
||||
})
|
||||
|
||||
} else {
|
||||
|
||||
// Show error message
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$uploadExternalFiles = async function(event, parent_id) {
|
||||
|
||||
// Prevent submit empty files
|
||||
if (event.dataTransfer.items.length == 0) return
|
||||
|
||||
// Get files
|
||||
const files = [...event.dataTransfer.items].map(item => item.getAsFile());
|
||||
|
||||
// Check storage size
|
||||
if (! this.$isThisLocation(['public']) && this.$store.getters.app.storage.percentage >= 100) {
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😬😬😬',
|
||||
title: this.$t('popup_exceed_limit.title'),
|
||||
message: this.$t('popup_exceed_limit.message')
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let fileCountSucceed = 1
|
||||
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: files.length
|
||||
})
|
||||
|
||||
for (var i = files.length - 1; i >= 0; i--) {
|
||||
|
||||
let formData = new FormData()
|
||||
|
||||
// Append data
|
||||
formData.append('file', files[i])
|
||||
|
||||
// Append form data
|
||||
formData.append('parent_id', parent_id)
|
||||
|
||||
// Upload data
|
||||
await store.dispatch('uploadFiles', formData).then(() => {
|
||||
// Progress file log
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: files.length
|
||||
})
|
||||
// Progress file log
|
||||
store.commit('INCREASE_FOLDER_ITEM', parent_id)
|
||||
|
||||
// Uploading finished
|
||||
if (files.length === fileCountSucceed) {
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
|
||||
} else {
|
||||
// Add uploaded file
|
||||
fileCountSucceed++
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
if (error.response.status == 423) {
|
||||
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😬😬😬',
|
||||
title: this.$t('popup_exceed_limit.title'),
|
||||
message: this.$t('popup_exceed_limit.message')
|
||||
})
|
||||
|
||||
} else if (error.response.status === 413) {
|
||||
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😟',
|
||||
title: this.$t('popup_paylod_error.title'),
|
||||
message: this.$t('popup_paylod_error.message')
|
||||
})
|
||||
install(Vue) {
|
||||
|
||||
Vue.prototype.$updateText = debounce(function (route, name, value) {
|
||||
|
||||
if (value === '') return
|
||||
|
||||
axios.patch(this.$store.getters.api + route, {name, value})
|
||||
.catch(error => {
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
})
|
||||
}, 300)
|
||||
|
||||
Vue.prototype.$getCreditCardBrand = function (brand) {
|
||||
return `/assets/icons/${brand}.svg`
|
||||
}
|
||||
|
||||
Vue.prototype.$updateImage = function (route, name, image) {
|
||||
|
||||
// Create form
|
||||
let formData = new FormData()
|
||||
|
||||
// Add image to form
|
||||
formData.append(name, image)
|
||||
formData.append('_method', 'PATCH')
|
||||
|
||||
axios.post(this.$store.getters.api + route, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Vue.prototype.$openImageOnNewTab = function (source) {
|
||||
let win = window.open(source, '_blank')
|
||||
|
||||
win.focus()
|
||||
}
|
||||
|
||||
Vue.prototype.$createFolder = function (folderName) {
|
||||
this.$store.dispatch('createFolder', folderName)
|
||||
}
|
||||
|
||||
Vue.prototype.$uploadFiles = async function (files) {
|
||||
// Prevent submit empty files
|
||||
if (files && files.length == 0) return
|
||||
|
||||
let fileCount = files ? files.length : 0
|
||||
let fileCountSucceed = 1
|
||||
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: fileCount
|
||||
})
|
||||
|
||||
// Get parent id
|
||||
const rootFolder = this.$store.getters.currentFolder
|
||||
? this.$store.getters.currentFolder.unique_id
|
||||
: 0
|
||||
|
||||
for (var i = files.length - 1; i >= 0; i--) {
|
||||
let formData = new FormData()
|
||||
|
||||
// Append data
|
||||
formData.append('file', files[i])
|
||||
|
||||
// Append form data
|
||||
formData.append('parent_id', rootFolder)
|
||||
|
||||
// Upload data
|
||||
await store.dispatch('uploadFiles', formData)
|
||||
.then(() => {
|
||||
// Progress file log
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: fileCount
|
||||
})
|
||||
|
||||
// Uploading finished
|
||||
if (fileCount === fileCountSucceed) {
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
|
||||
} else {
|
||||
// Add uploaded file
|
||||
fileCountSucceed++
|
||||
}
|
||||
}).catch(error => {
|
||||
switch (error.response.status) {
|
||||
case 423:
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😬',
|
||||
title: this.$t('popup_exceed_limit.title'),
|
||||
message: this.$t('popup_exceed_limit.message')
|
||||
})
|
||||
break;
|
||||
case 413:
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😟',
|
||||
title: this.$t('popup_paylod_error.title'),
|
||||
message: this.$t('popup_paylod_error.message')
|
||||
})
|
||||
break;
|
||||
default:
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$uploadExternalFiles = async function (event, parent_id) {
|
||||
|
||||
// Prevent submit empty files
|
||||
if (event.dataTransfer.items.length == 0) return
|
||||
|
||||
// Get files
|
||||
const files = [...event.dataTransfer.items].map(item => item.getAsFile());
|
||||
|
||||
let fileCountSucceed = 1
|
||||
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: files.length
|
||||
})
|
||||
|
||||
for (var i = files.length - 1; i >= 0; i--) {
|
||||
|
||||
let formData = new FormData()
|
||||
|
||||
// Append data
|
||||
formData.append('file', files[i])
|
||||
|
||||
// Append form data
|
||||
formData.append('parent_id', parent_id)
|
||||
|
||||
// Upload data
|
||||
await store.dispatch('uploadFiles', formData).then(() => {
|
||||
// Progress file log
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
|
||||
current: fileCountSucceed,
|
||||
total: files.length
|
||||
})
|
||||
// Progress file log
|
||||
store.commit('INCREASE_FOLDER_ITEM', parent_id)
|
||||
|
||||
// Uploading finished
|
||||
if (files.length === fileCountSucceed) {
|
||||
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
|
||||
} else {
|
||||
// Add uploaded file
|
||||
fileCountSucceed++
|
||||
}
|
||||
}).catch(error => {
|
||||
switch (error.response.status) {
|
||||
case 423:
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😬',
|
||||
title: this.$t('popup_exceed_limit.title'),
|
||||
message: this.$t('popup_exceed_limit.message')
|
||||
})
|
||||
break;
|
||||
case 413:
|
||||
events.$emit('alert:open', {
|
||||
emoji: '😟',
|
||||
title: this.$t('popup_paylod_error.title'),
|
||||
message: this.$t('popup_paylod_error.message')
|
||||
})
|
||||
break;
|
||||
default:
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$downloadFile = function (url, filename) {
|
||||
var anchor = document.createElement('a')
|
||||
|
||||
anchor.href = url
|
||||
|
||||
anchor.download = filename
|
||||
|
||||
document.body.appendChild(anchor)
|
||||
|
||||
anchor.click()
|
||||
}
|
||||
|
||||
Vue.prototype.$closePopup = function () {
|
||||
events.$emit('popup:close')
|
||||
}
|
||||
|
||||
Vue.prototype.$isThisRoute = function (route, locations) {
|
||||
|
||||
return includes(locations, route.name)
|
||||
}
|
||||
|
||||
Vue.prototype.$isThisLocation = function (location) {
|
||||
|
||||
// Get current location
|
||||
let currentLocation = store.getters.currentFolder && store.getters.currentFolder.location ? store.getters.currentFolder.location : undefined
|
||||
|
||||
// Check if type is object
|
||||
if (typeof location === 'Object' || location instanceof Object) {
|
||||
return includes(location, currentLocation)
|
||||
|
||||
} else {
|
||||
return currentLocation === location
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$checkPermission = function (type) {
|
||||
|
||||
let currentPermission = store.getters.permission
|
||||
|
||||
// Check if type is object
|
||||
if (typeof type === 'Object' || type instanceof Object) {
|
||||
return includes(type, currentPermission)
|
||||
|
||||
} else {
|
||||
return currentPermission === type
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$isMobile = function () {
|
||||
const toMatch = [
|
||||
/Android/i,
|
||||
/webOS/i,
|
||||
/iPhone/i,
|
||||
/iPad/i,
|
||||
/iPod/i,
|
||||
/BlackBerry/i,
|
||||
/Windows Phone/i
|
||||
]
|
||||
|
||||
return toMatch.some(toMatchItem => {
|
||||
return navigator.userAgent.match(toMatchItem)
|
||||
})
|
||||
}
|
||||
|
||||
Vue.prototype.$isMinimalScale = function () {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'minimal-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isCompactScale = function () {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'compact-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isFullScale = function () {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'full-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isSomethingWrong = function () {
|
||||
|
||||
} else {
|
||||
|
||||
// Show error message
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$downloadFile = function(url, filename) {
|
||||
var anchor = document.createElement('a')
|
||||
|
||||
anchor.href = url
|
||||
|
||||
anchor.download = filename
|
||||
|
||||
document.body.appendChild(anchor)
|
||||
|
||||
anchor.click()
|
||||
}
|
||||
|
||||
Vue.prototype.$closePopup = function() {
|
||||
events.$emit('popup:close')
|
||||
}
|
||||
|
||||
Vue.prototype.$isThisRoute = function(route, locations) {
|
||||
|
||||
return includes(locations, route.name)
|
||||
}
|
||||
|
||||
Vue.prototype.$isThisLocation = function(location) {
|
||||
|
||||
// Get current location
|
||||
let currentLocation = store.getters.currentFolder && store.getters.currentFolder.location ? store.getters.currentFolder.location : undefined
|
||||
|
||||
// Check if type is object
|
||||
if (typeof location === 'Object' || location instanceof Object) {
|
||||
return includes(location, currentLocation)
|
||||
|
||||
} else {
|
||||
return currentLocation === location
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$checkPermission = function(type) {
|
||||
|
||||
let currentPermission = store.getters.permission
|
||||
|
||||
// Check if type is object
|
||||
if (typeof type === 'Object' || type instanceof Object) {
|
||||
return includes(type, currentPermission)
|
||||
|
||||
} else {
|
||||
return currentPermission === type
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$isMobile = function() {
|
||||
const toMatch = [
|
||||
/Android/i,
|
||||
/webOS/i,
|
||||
/iPhone/i,
|
||||
/iPad/i,
|
||||
/iPod/i,
|
||||
/BlackBerry/i,
|
||||
/Windows Phone/i
|
||||
]
|
||||
|
||||
return toMatch.some(toMatchItem => {
|
||||
return navigator.userAgent.match(toMatchItem)
|
||||
})
|
||||
}
|
||||
|
||||
Vue.prototype.$isMinimalScale = function() {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'minimal-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isCompactScale = function() {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'compact-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isFullScale = function() {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'full-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isSomethingWrong = function() {
|
||||
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
}
|
||||
}
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Helpers
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
"message": "Something went wrong and we can't continue. Please contact us."
|
||||
},
|
||||
"popup_exceed_limit": {
|
||||
"title": "Whooops, you exceed your storage limit :(",
|
||||
"title": "Whooops, you exceed storage limit :(",
|
||||
"message": "Please contact your administrator to change your limit."
|
||||
},
|
||||
"popup_share_create": {
|
||||
|
||||
10
resources/js/router.js
vendored
@@ -15,6 +15,7 @@ import Profile from './views/User/Settings'
|
||||
import Invoice from './views/User/Invoices'
|
||||
import Password from './views/User/Password'
|
||||
import Subscription from './views/User/Subscription'
|
||||
import PaymentCards from './views/User/PaymentCards'
|
||||
|
||||
import Trash from './views/FilePages/Trash'
|
||||
import Files from './views/FilePages/Files'
|
||||
@@ -399,6 +400,15 @@ const routesUser = [
|
||||
title: 'Subscription'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'PaymentCards',
|
||||
path: '/settings/payment-cards',
|
||||
component: PaymentCards,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: 'Payment Cards'
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
26
resources/js/store/modules/userAuth.js
vendored
@@ -11,22 +11,26 @@ const defaultState = {
|
||||
|
||||
const actions = {
|
||||
getAppData: ({commit, getters}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get(getters.api + '/user')
|
||||
.then((response) => {
|
||||
resolve(response)
|
||||
|
||||
axios
|
||||
.get(getters.api + '/user')
|
||||
.then((response) => {
|
||||
commit('RETRIEVE_USER', response.data)
|
||||
commit('RETRIEVE_USER', response.data)
|
||||
|
||||
}).catch((error) => {
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
|
||||
// Redirect if unauthenticated
|
||||
if ([401, 403].includes(error.response.status)) {
|
||||
// Redirect if unauthenticated
|
||||
if ([401, 403].includes(error.response.status)) {
|
||||
|
||||
commit('SET_AUTHORIZED', false)
|
||||
router.push({name: 'SignIn'})
|
||||
commit('SET_AUTHORIZED', false)
|
||||
router.push({name: 'SignIn'})
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
})
|
||||
},
|
||||
logOut: ({getters, commit}) => {
|
||||
axios
|
||||
|
||||
@@ -27,12 +27,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.payments_processed }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.active_subscribers }}
|
||||
{{ row.data.attributes.payment_processed }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
@@ -100,12 +95,7 @@
|
||||
},
|
||||
{
|
||||
label: 'Payments Processed',
|
||||
field: 'data.attributes.payments_processed',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Active Subscribers',
|
||||
field: 'data.attributes.active_subscribers',
|
||||
field: 'data.attributes.payment_processed',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,47 +1,68 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<PageTabGroup>
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="invoices" class="table">
|
||||
<PageTabGroup v-if="transactions.length > 0">
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="transactions" class="table">
|
||||
<template scope="{ row }">
|
||||
<tr>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
${{ row.attributes.total }}
|
||||
</span>
|
||||
<a :href="'/invoice/' + row.data.attributes.token" target="_blank" class="cell-item">
|
||||
{{ row.data.attributes.order }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.attributes.plan }}
|
||||
</span>
|
||||
<span class="cell-item">
|
||||
${{ row.data.attributes.total }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.attributes.created_at_formatted }}
|
||||
</span>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.bag[0].description }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.created_at_formatted }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<router-link :to="{name: 'UserInvoices', params: {id: row.relationships.user.data.id}}">
|
||||
<DatatableCellImage
|
||||
image-size="small"
|
||||
:image="row.relationships.user.data.attributes.avatar"
|
||||
:title="row.relationships.user.data.attributes.name"
|
||||
/>
|
||||
</router-link>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-icons">
|
||||
<download-cloud-icon size="15" class="icon"></download-cloud-icon>
|
||||
<a :href="'/invoice/' + row.data.attributes.token" target="_blank">
|
||||
<external-link-icon size="15" class="icon"></external-link-icon>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</DatatableWrapper>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
You don't have any transactions yet.
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatatableCellImage from '@/components/Others/Tables/DatatableCellImage'
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import {DownloadCloudIcon} from "vue-feather-icons";
|
||||
import {ExternalLinkIcon} from "vue-feather-icons";
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'GatewayTransactions',
|
||||
components: {
|
||||
DownloadCloudIcon,
|
||||
DatatableCellImage,
|
||||
ExternalLinkIcon,
|
||||
DatatableWrapper,
|
||||
PageTabGroup,
|
||||
PageTab,
|
||||
@@ -49,97 +70,13 @@
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
invoices: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 49.99,
|
||||
plan: 'Business Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 29.99,
|
||||
plan: 'Professional Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 49.99,
|
||||
plan: 'Business Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 29.99,
|
||||
plan: 'Professional Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
},
|
||||
],
|
||||
transactions: [],
|
||||
columns: [
|
||||
{
|
||||
label: 'Invoice Number',
|
||||
field: 'attributes.total',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Total',
|
||||
field: 'attributes.total',
|
||||
@@ -155,6 +92,11 @@
|
||||
field: 'attributes.created_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'User',
|
||||
field: 'relationships.user.data.id',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
@@ -164,11 +106,11 @@
|
||||
}
|
||||
},
|
||||
created() {
|
||||
/*axios.get('/api/users/' + this.$route.params.id + '/storage')
|
||||
axios.get('/api/gateways/' + this.$route.params.slug + '/transactions')
|
||||
.then(response => {
|
||||
this.storage = response.data.data
|
||||
this.transactions = response.data.data
|
||||
this.isLoading = false
|
||||
})*/
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -34,15 +34,6 @@
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<!--Price-->
|
||||
<div class="block-wrapper">
|
||||
<label>Price:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Plan price" rules="required" v-slot="{ errors }">
|
||||
<input @input="$updateText('/plans/' + $route.params.id + '/update', 'price', plan.attributes.price)" v-model="plan.attributes.price" placeholder="Plan price" type="number" step="0.01" min="1" max="99999" :class="{'is-error': errors[0]}"/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<!--Storage Capacity-->
|
||||
<div class="block-wrapper">
|
||||
<label>Storage Capacity:</label>
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
</ColorLabel>
|
||||
</td>
|
||||
<td v-if="config.isSaaS">
|
||||
<span class="cell-item" v-if="row.relationships.subscription">
|
||||
{{ row.relationships.subscription.data.attributes.name }}
|
||||
<span class="cell-item" v-if="row.data.attributes.subscription">
|
||||
Premium
|
||||
</span>
|
||||
<span class="cell-item" v-else>
|
||||
Free
|
||||
@@ -114,44 +114,7 @@
|
||||
return {
|
||||
isLoading: true,
|
||||
users: [],
|
||||
columns: [
|
||||
{
|
||||
label: this.$t('admin_page_user.table.name'),
|
||||
field: 'data.attributes.name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.role'),
|
||||
field: 'data.attributes.role',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Subscription Plan',
|
||||
field: 'data.attributes.role',
|
||||
sortable: true,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_used'),
|
||||
field: 'data.attributes.storage.used',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_capacity'),
|
||||
field: 'data.attributes.storage.capacity',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.created_at'),
|
||||
field: 'data.attributes.created_at_formatted',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
columns: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -167,6 +130,45 @@
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.columns = [
|
||||
{
|
||||
label: this.$t('admin_page_user.table.name'),
|
||||
field: 'data.attributes.name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.role'),
|
||||
field: 'data.attributes.role',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Subscription Plan',
|
||||
field: 'data.attributes.role',
|
||||
sortable: true,
|
||||
hidden: ! this.config.isSaaS,
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_used'),
|
||||
field: 'data.attributes.storage.used',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_capacity'),
|
||||
field: 'data.attributes.storage.capacity',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.created_at'),
|
||||
field: 'data.attributes.created_at_formatted',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
sortable: false
|
||||
},
|
||||
]
|
||||
|
||||
axios.get('/api/users')
|
||||
.then(response => {
|
||||
this.users = response.data.data
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="config.isSaaS" class="headline-actions">
|
||||
<router-link :to="{name: 'UpgradePlan'}">
|
||||
<router-link :to="{name: 'UpgradePlan'}" v-if="! user.relationships.subscription || (user.relationships.subscription && ! user.relationships.subscription.data.attributes.is_highest)">
|
||||
<ButtonBase button-style="secondary" type="button">
|
||||
Upgrade Plan
|
||||
</ButtonBase>
|
||||
@@ -56,13 +56,22 @@
|
||||
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'Subscription'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<credit-card-icon size="17"></credit-card-icon>
|
||||
<cloud-icon size="17"></cloud-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
Subscription
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'PaymentCards'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<credit-card-icon size="17"></credit-card-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
Payment Cards
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'Invoice'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<file-text-icon size="17"></file-text-icon>
|
||||
@@ -105,6 +114,7 @@
|
||||
CreditCardIcon,
|
||||
HardDriveIcon,
|
||||
FileTextIcon,
|
||||
CloudIcon,
|
||||
UserIcon,
|
||||
LockIcon,
|
||||
} from 'vue-feather-icons'
|
||||
@@ -112,6 +122,7 @@
|
||||
export default {
|
||||
name: 'Settings',
|
||||
components: {
|
||||
CloudIcon,
|
||||
ButtonBase,
|
||||
CreditCardIcon,
|
||||
UserImageInput,
|
||||
@@ -127,10 +138,10 @@
|
||||
computed: {
|
||||
...mapGetters(['user', 'config']),
|
||||
subscriptionStatus() {
|
||||
return this.user.relationships.subscription ? 'Premium' : 'Free'
|
||||
return this.user.data.attributes.subscription ? 'Premium' : 'Free'
|
||||
},
|
||||
subscriptionColor() {
|
||||
return this.user.relationships.subscription ? 'green' : 'purple'
|
||||
return this.user.data.attributes.subscription ? 'green' : 'purple'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
|
||||
@@ -13,118 +13,186 @@
|
||||
</div>
|
||||
|
||||
<div class="order">
|
||||
<div class="billing" v-if="billing">
|
||||
<b class="form-group-label">Billing Information:</b>
|
||||
<ValidationObserver ref="order" v-slot="{ invalid }" tag="form" class="form block-form">
|
||||
<div class="form block-form">
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Name:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_name" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_name"
|
||||
placeholder="Type your billing name"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="steps">
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Address:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_address" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_address"
|
||||
placeholder="Type your billing address"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="payment-card">
|
||||
<b class="form-group-label">Payment Card:</b>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_state" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_state"
|
||||
placeholder="Type your billing state"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<!-- Pay by new credit card -->
|
||||
<div class="register-card" v-show="! defaultPaymentCard || payByNewCard">
|
||||
<p class="payment-demo-disclaimer">
|
||||
For test your payment please use <b>4242 4242 4242 4242</b> as a card number, <b>11/22</b>
|
||||
as the expiration date and <b>123</b> as CVC number and ZIP <b>12345</b>.
|
||||
</p>
|
||||
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>City:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required" name="billing_city" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_city"
|
||||
placeholder="Type your billing city"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div ref="stripeCard" class="stripe-card" :class="{'is-error': isError }"></div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Postal Code:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required" name="billing_postal_code"
|
||||
v-slot="{ errors }">
|
||||
<input v-model="billing.billing_postal_code"
|
||||
placeholder="Type your billing postal code"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Country:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_country" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_country"
|
||||
placeholder="Type your billing country"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Phone Number:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_phone_number" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_phone_number"
|
||||
placeholder="Type your billing phone number"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
<div class="card-error-message" v-if="isError">
|
||||
<span>{{ errorMessage }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</ValidationObserver>
|
||||
|
||||
<!--User registered payment card-->
|
||||
<div class="registered-cards" v-if="defaultPaymentCard && ! payByNewCard">
|
||||
|
||||
<div class="credit-card" :class="{'is-error': isError}">
|
||||
<div class="card-number">
|
||||
<img class="credit-card-icon"
|
||||
:src="$getCreditCardBrand(defaultPaymentCard.data.attributes.brand)"
|
||||
:alt="defaultPaymentCard.data.attributes.brand">
|
||||
<div class="credit-card-numbers">
|
||||
•••• {{ defaultPaymentCard.data.attributes.last4 }}
|
||||
</div>
|
||||
<ColorLabel color="purple">Default</ColorLabel>
|
||||
</div>
|
||||
<div class="expiration-date">
|
||||
<span>{{ defaultPaymentCard.data.attributes.exp_month }} / {{ defaultPaymentCard.data.attributes.exp_year }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Change payment-->
|
||||
<div class="change-payment" v-if="! isError">
|
||||
<span>Also you can</span>
|
||||
|
||||
<router-link v-if="paymentCards.data.length > 0" :to="{name: 'PaymentCards'}">change your
|
||||
default payment method
|
||||
</router-link>
|
||||
<span v-if="paymentCards.data.length > 0">or</span>
|
||||
|
||||
<a @click="payByNewCardForm">pay by new credit card.</a>
|
||||
</div>
|
||||
|
||||
<!--Card error-->
|
||||
<div class="card-error-message" v-if="isError">
|
||||
<span>{{ errorMessage }}</span>
|
||||
<span @click="payByNewCardForm"
|
||||
class="link">Please pay by another payment card</span>
|
||||
<span> or </span>
|
||||
<router-link :to="{name: 'PaymentCards'}" class="link">Change your default payment
|
||||
method
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="billing" v-if="billing">
|
||||
<b class="form-group-label">Billing Information:</b>
|
||||
<ValidationObserver ref="order" v-slot="{ invalid }" tag="form" class="form block-form">
|
||||
<div class="form block-form">
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Name:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required"
|
||||
name="billing_name" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_name"
|
||||
placeholder="Type your billing name"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Address:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required"
|
||||
name="billing_address" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_address"
|
||||
placeholder="Type your billing address"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required"
|
||||
name="billing_state" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_state"
|
||||
placeholder="Type your billing state"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>City:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required" name="billing_city"
|
||||
v-slot="{ errors }">
|
||||
<input v-model="billing.billing_city"
|
||||
placeholder="Type your billing city"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Postal Code:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required" name="billing_postal_code"
|
||||
v-slot="{ errors }">
|
||||
<input v-model="billing.billing_postal_code"
|
||||
placeholder="Type your billing postal code"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Country:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required"
|
||||
name="billing_country" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_country"
|
||||
placeholder="Type your billing country"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Phone Number:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required"
|
||||
name="billing_phone_number" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_phone_number"
|
||||
placeholder="Type your billing phone number"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<b class="form-group-label">Order Summary:</b>
|
||||
|
||||
<div class="summary-list" v-if="requestedPlan">
|
||||
<div class="summary-list" :class="{'is-error': isError}" v-if="requestedPlan">
|
||||
<div class="row">
|
||||
<div class="cell">
|
||||
<b>{{ requestedPlan.data.attributes.name }}</b>
|
||||
<small>Billed monthly</small>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<b>{{ requestedPlan.data.attributes.price }} USD</b>
|
||||
<b>{{ requestedPlan.data.attributes.price }}</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -132,15 +200,14 @@
|
||||
<b>Total</b>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<b>{{ requestedPlan.data.attributes.price }} USD</b>
|
||||
<b>{{ requestedPlan.data.attributes.price }}</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ButtonBase :disabled="isSubmitted" :loading="isSubmitted" @click.native="submitOrder"
|
||||
type="submit" button-style="theme-solid" class="next-submit">
|
||||
Pay Order
|
||||
Pay with credit card
|
||||
</ButtonBase>
|
||||
|
||||
<p class="error-message" v-if="isError">{{ errorMessage }}</p>
|
||||
<small class="disclaimer">
|
||||
By submit form, you agree to save the payment method and billing information in your
|
||||
VueFileManager account.
|
||||
@@ -148,7 +215,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="loader" v-if="isLoading">
|
||||
@@ -162,14 +228,19 @@
|
||||
import PlanPricingTables from '@/components/Others/PlanPricingTables'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import ColorLabel from '@/components/Others/ColorLabel'
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {CreditCardIcon} from 'vue-feather-icons'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import { mapGetters } from 'vuex'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
import axios from 'axios'
|
||||
|
||||
let stripe = Stripe(`pk_test_51GsACaCBETHMUxzVsYkeApHtqb85paMuye7G77PDDQ28kXqDJ5HTmqLi13aM6xee81OQK1fhkTZ7vmDiWLStU9160061Yb2MtL`),
|
||||
elements = stripe.elements(),
|
||||
card = undefined;
|
||||
|
||||
export default {
|
||||
name: 'UpgradePlan',
|
||||
components: {
|
||||
@@ -180,20 +251,66 @@
|
||||
MobileHeader,
|
||||
ButtonBase,
|
||||
PageHeader,
|
||||
ColorLabel,
|
||||
required,
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['requestedPlan']),
|
||||
billing() {
|
||||
return this.$store.getters.user.relationships.settings.data.attributes
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
complete: false,
|
||||
stripeOptions: {
|
||||
hidePostalCode: false
|
||||
},
|
||||
isLoading: true,
|
||||
isSubmitted: false,
|
||||
billing: undefined,
|
||||
paymentCards: undefined,
|
||||
defaultPaymentCard: undefined,
|
||||
|
||||
errorMessage: undefined,
|
||||
isError: false,
|
||||
|
||||
payByNewCard: false,
|
||||
|
||||
clientSecret: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
payByNewCardForm() {
|
||||
this.payByNewCard = true
|
||||
this.isError = false
|
||||
},
|
||||
successOrder() {
|
||||
// Update user data
|
||||
//this.$store.dispatch('getAppData')
|
||||
|
||||
// End loading
|
||||
this.isSubmitted = false
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: 'Your account was successfully upgraded.',
|
||||
})
|
||||
|
||||
// Go to User page
|
||||
//this.$router.push({name: 'Subscription'})
|
||||
},
|
||||
errorOrder(error) {
|
||||
|
||||
if (error.response.status = 402) {
|
||||
this.isError = true
|
||||
this.errorMessage = error.response.data.message
|
||||
}
|
||||
|
||||
// End loading
|
||||
this.isSubmitted = false
|
||||
},
|
||||
async submitOrder() {
|
||||
|
||||
// Validate fields
|
||||
@@ -201,56 +318,89 @@
|
||||
|
||||
if (!isValid) return;
|
||||
|
||||
// Remove error
|
||||
this.isError = false
|
||||
|
||||
// Start loading
|
||||
this.isSubmitted = true
|
||||
|
||||
// Send order request
|
||||
axios
|
||||
.post('/api/subscription/upgrade', {
|
||||
billing: this.billing,
|
||||
plan: this.requestedPlan,
|
||||
// If user don't have credit card, register new
|
||||
if (!this.defaultPaymentCard || this.payByNewCard) {
|
||||
|
||||
console.log('Payment by new card');
|
||||
|
||||
const {setupIntent, error} = await stripe.confirmCardSetup(this.clientSecret, {
|
||||
payment_method: {
|
||||
card: card,
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// Update user data
|
||||
this.$store.dispatch('getAppData')
|
||||
if (error) {
|
||||
|
||||
// End loading
|
||||
// Set error on
|
||||
this.isError = true
|
||||
|
||||
// End button spinner
|
||||
this.isSubmitted = false
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: 'Your account was successfully upgraded.',
|
||||
// Show error message
|
||||
this.errorMessage = error.message
|
||||
|
||||
} else {
|
||||
|
||||
axios
|
||||
.post('/api/subscription/upgrade', {
|
||||
billing: this.billing,
|
||||
plan: this.requestedPlan,
|
||||
payment: {
|
||||
type: 'stripe',
|
||||
meta: {
|
||||
pm: setupIntent.payment_method,
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => this.successOrder())
|
||||
.catch((error) => this.errorOrder(error))
|
||||
}
|
||||
}
|
||||
|
||||
// if user has credit card
|
||||
if (this.defaultPaymentCard && !this.payByNewCard) {
|
||||
|
||||
console.log('Payment by default card');
|
||||
|
||||
axios
|
||||
.post('/api/subscription/upgrade', {
|
||||
billing: this.billing,
|
||||
plan: this.requestedPlan,
|
||||
payment: {
|
||||
type: 'stripe',
|
||||
}
|
||||
})
|
||||
|
||||
// Go to User page
|
||||
this.$router.push({name: 'Storage'})
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
// End loading
|
||||
this.isSubmitted = false
|
||||
})
|
||||
}
|
||||
.then(() => this.successOrder())
|
||||
.catch((error) => this.errorOrder(error))
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted: function () {
|
||||
card = elements.create('card');
|
||||
card.mount(this.$refs.stripeCard);
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/user')
|
||||
|
||||
// Get setup intent for stripe
|
||||
axios.get('/api/stripe/setup-intent')
|
||||
.then(response => this.clientSecret = response.data.client_secret)
|
||||
|
||||
axios.get('/api/user/payments')
|
||||
.then(response => {
|
||||
|
||||
if (! this.requestedPlan) {
|
||||
if (!this.requestedPlan) {
|
||||
this.$router.push({name: 'UpgradePlan'})
|
||||
}
|
||||
|
||||
this.billing = {
|
||||
billing_name: response.data.relationships.settings.data.attributes.billing_name,
|
||||
billing_address: response.data.relationships.settings.data.attributes.billing_address,
|
||||
billing_state: response.data.relationships.settings.data.attributes.billing_state,
|
||||
billing_city: response.data.relationships.settings.data.attributes.billing_city,
|
||||
billing_postal_code: response.data.relationships.settings.data.attributes.billing_postal_code,
|
||||
billing_country: response.data.relationships.settings.data.attributes.billing_country,
|
||||
billing_phone_number: response.data.relationships.settings.data.attributes.billing_phone_number,
|
||||
}
|
||||
this.defaultPaymentCard = response.data.default
|
||||
this.paymentCards = response.data.others
|
||||
|
||||
this.isLoading = false
|
||||
})
|
||||
@@ -263,6 +413,133 @@
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.change-payment {
|
||||
padding-top: 10px;
|
||||
|
||||
span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
span, a {
|
||||
color: $text-muted;
|
||||
@include font-size(14);
|
||||
}
|
||||
}
|
||||
|
||||
.card-error-message {
|
||||
padding-top: 10px;
|
||||
|
||||
span, a {
|
||||
@include font-size(14);
|
||||
font-weight: 600;
|
||||
color: $danger;
|
||||
}
|
||||
|
||||
.link, a {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.registered-cards {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.register-card {
|
||||
margin-bottom: 55px;
|
||||
}
|
||||
|
||||
.credit-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 15px;
|
||||
background: $light_background;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
|
||||
&.is-error {
|
||||
box-shadow: 0 0 7px rgba($danger, 0.3);
|
||||
border: 2px solid $danger;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.card-number {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.credit-card-numbers {
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.credit-card-icon {
|
||||
vertical-align: middle;
|
||||
max-height: 20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-demo-disclaimer {
|
||||
padding: 15px;
|
||||
background: $light_background;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.6;
|
||||
|
||||
b {
|
||||
color: $danger;
|
||||
}
|
||||
}
|
||||
|
||||
.stripe-card {
|
||||
box-sizing: border-box;
|
||||
padding: 13px 20px;
|
||||
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
|
||||
box-shadow: 0 1px 3px 0 #e6ebf1;
|
||||
-webkit-transition: box-shadow 150ms ease;
|
||||
transition: box-shadow 150ms ease;
|
||||
|
||||
&.is-error {
|
||||
box-shadow: 0 0 7px rgba($danger, 0.3);
|
||||
border: 2px solid $danger;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&.StripeElement--focus {
|
||||
box-shadow: 0 1px 3px 0 #cfd7df;
|
||||
}
|
||||
|
||||
&.StripeElement--invalid {
|
||||
border-color: #fa755a;
|
||||
}
|
||||
|
||||
&.StripeElement--webkit-autofill {
|
||||
background-color: #fefde5 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.summary-list {
|
||||
box-shadow: 0 7px 20px 5px hsla(220, 36%, 16%, 0.06);
|
||||
border-radius: 8px;
|
||||
@@ -270,6 +547,15 @@
|
||||
padding: 25px;
|
||||
top: 30px;
|
||||
|
||||
&.is-error {
|
||||
border: 2px solid $danger;
|
||||
box-shadow: 0 7px 20px 5px rgba($danger, 0.06);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.next-submit {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
@@ -317,7 +603,7 @@
|
||||
.order {
|
||||
display: flex;
|
||||
|
||||
.billing {
|
||||
.steps {
|
||||
flex: 0 0 65%;
|
||||
padding-right: 30px;
|
||||
|
||||
|
||||
@@ -49,6 +49,12 @@
|
||||
this.$store.commit('STORE_REQUESTED_PLAN', plan)
|
||||
}
|
||||
},
|
||||
/*beforeMount() {
|
||||
let StripeElementsScript = document.createElement('script')
|
||||
|
||||
StripeElementsScript.setAttribute('src', 'https://js.stripe.com/v3/')
|
||||
document.head.appendChild(StripeElementsScript)
|
||||
},*/
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
244
resources/js/views/User/PaymentCards.vue
Normal file
@@ -0,0 +1,244 @@
|
||||
<template>
|
||||
<PageTab :is-loading="isLoading">
|
||||
<PageTabGroup v-if="paymentCards && paymentCards.length > 0">
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="paymentCards" class="table">
|
||||
<template scope="{ row }">
|
||||
<tr :class="{'is-deleting': row.data.attributes.card_id === deletingID}">
|
||||
<td style="width: 300px">
|
||||
<span class="cell-item">
|
||||
<div class="credit-card">
|
||||
<img class="credit-card-icon" :src="$getCreditCardBrand(row.data.attributes.brand)"
|
||||
:alt="row.data.attributes.brand">
|
||||
<div class="credit-card-numbers">
|
||||
•••• {{ row.data.attributes.last4 }}
|
||||
</div>
|
||||
<ColorLabel v-if="row.data.id === defaultPaymentCard.data.id" color="purple">Default</ColorLabel>
|
||||
</div>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
<ColorLabel :color="getCardStatusColor(row.data.attributes.status)">{{ getCardStatus(row.data.attributes.status) }}</ColorLabel>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.exp_month }} / {{ row.data.attributes.exp_year }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-icons">
|
||||
<credit-card-icon size="15" class="icon icon-card" title="Set as default card" @click="setDefaultCard(row.data.attributes)" v-if="row.data.id !== defaultPaymentCard.data.id"></credit-card-icon>
|
||||
<trash2-icon size="15" class="icon icon-trash" title="Delete card" @click="deleteCard(row.data.attributes)"></trash2-icon>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</DatatableWrapper>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
You don't have any payment cards yet.
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import ColorLabel from '@/components/Others/ColorLabel'
|
||||
import {CreditCardIcon, Trash2Icon} from "vue-feather-icons"
|
||||
import {events} from "@/bus"
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'UserPaymentCards',
|
||||
components: {
|
||||
DatatableWrapper,
|
||||
PageTabGroup,
|
||||
Trash2Icon,
|
||||
ColorLabel,
|
||||
CreditCardIcon,
|
||||
PageTab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultPaymentCard: undefined,
|
||||
paymentCards: undefined,
|
||||
deletingID: undefined,
|
||||
columns: [
|
||||
{
|
||||
label: 'Card Number',
|
||||
field: 'data.attributes.total',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Status',
|
||||
field: 'data.attributes.status',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Expiration Date',
|
||||
field: 'data.attributes.total',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
isLoading: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCardStatusColor(status) {
|
||||
switch (status) {
|
||||
case 'active':
|
||||
return 'green'
|
||||
break
|
||||
case 'card_declined':
|
||||
return 'yellow'
|
||||
break
|
||||
case 'expired':
|
||||
return 'red'
|
||||
break
|
||||
}
|
||||
},
|
||||
getCardStatus(status) {
|
||||
switch (status) {
|
||||
case 'active':
|
||||
return 'Active'
|
||||
break
|
||||
case 'card_declined':
|
||||
return 'Rejected'
|
||||
break
|
||||
case 'expired':
|
||||
return 'Expired'
|
||||
break
|
||||
}
|
||||
},
|
||||
setDefaultCard(card) {
|
||||
events.$emit('confirm:open', {
|
||||
title: 'Set as default card?',
|
||||
message: 'Your card will be set as default and will be always charged for the next billings.',
|
||||
buttonColor: 'theme-solid',
|
||||
action: {
|
||||
id: card.card_id,
|
||||
operation: 'set-as-default-credit-card'
|
||||
}
|
||||
})
|
||||
},
|
||||
deleteCard(card) {
|
||||
events.$emit('confirm:open', {
|
||||
title: 'Are you sure?',
|
||||
message: 'This event is irreversible and your payment card will be delete forever',
|
||||
action: {
|
||||
id: card.card_id,
|
||||
operation: 'delete-credit-card'
|
||||
}
|
||||
})
|
||||
},
|
||||
fetchPaymentCards() {
|
||||
axios.get('/api/user/payments')
|
||||
.then(response => {
|
||||
|
||||
this.defaultPaymentCard = response.data.default
|
||||
|
||||
this.paymentCards = response.data.others.data
|
||||
this.paymentCards.push(response.data.default)
|
||||
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
// Get payments card
|
||||
this.fetchPaymentCards()
|
||||
|
||||
// Delete credit card
|
||||
events.$on('action:confirmed', data => {
|
||||
|
||||
if (data.operation === 'delete-credit-card') {
|
||||
|
||||
this.deletingID = data.id
|
||||
|
||||
axios.delete('/api/user/payment-cards/' + data.id)
|
||||
.then(() => {
|
||||
|
||||
// Get payments card
|
||||
this.fetchPaymentCards()
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: 'Your card was successfully deleted.',
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
})
|
||||
}
|
||||
|
||||
if (data.operation === 'set-as-default-credit-card') {
|
||||
|
||||
axios.patch('/api/user/payment-cards/' + data.id, {
|
||||
default: 1
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// Get payments card
|
||||
this.fetchPaymentCards()
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: 'Your card was successfully set as default.',
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
events.$off('action:confirmed')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.is-deleting {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.credit-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.credit-card-numbers {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.credit-card-icon {
|
||||
max-height: 20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,34 +1,44 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<PageTab :is-loading="isLoading">
|
||||
<PageTabGroup v-if="subscription">
|
||||
|
||||
<!--Info about active subscription-->
|
||||
<div v-if="! subscription.canceled" class="state active">
|
||||
<div v-if="! subscription.data.attributes.canceled" class="state active">
|
||||
<ListInfo class="list-info">
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.name + ' - ' + subscription.capacity_formatted"/>
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.data.attributes.name + ' - ' + subscription.data.attributes.capacity_formatted"/>
|
||||
<ListInfoItem class="list-item" title="Billed" content="Monthly"/>
|
||||
<ListInfoItem class="list-item" title="Status" :content="status"/>
|
||||
<ListInfoItem class="list-item" title="Created At" :content="subscription.created_at"/>
|
||||
<ListInfoItem class="list-item" title="Renews At" :content="subscription.ends_at"/>
|
||||
<ListInfoItem class="list-item" title="Created At" :content="subscription.data.attributes.created_at"/>
|
||||
<ListInfoItem class="list-item" title="Renews At" :content="subscription.data.attributes.ends_at"/>
|
||||
</ListInfo>
|
||||
<div class="cancel-plan">
|
||||
<div class="plan-action">
|
||||
<ButtonBase
|
||||
:disabled="isDeleting"
|
||||
@click.native="cancelSubscription"
|
||||
:button-style="cancelButtonStyle"
|
||||
class="cancel-button">
|
||||
class="confirm-button">
|
||||
{{ cancelButtonText }}
|
||||
</ButtonBase>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Info about canceled subscription-->
|
||||
<div v-if="subscription.canceled" class="state canceled">
|
||||
<div v-if="subscription.data.attributes.canceled" class="state canceled">
|
||||
<ListInfo class="list-info">
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.name"/>
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.data.attributes.name"/>
|
||||
<ListInfoItem class="list-item" title="Status" :content="status"/>
|
||||
<ListInfoItem class="list-item" title="Canceled At" :content="subscription.canceled_at"/>
|
||||
<ListInfoItem class="list-item" title="Ends At" :content="subscription.ends_at"/>
|
||||
<ListInfoItem class="list-item" title="Canceled At" :content="subscription.data.attributes.canceled_at"/>
|
||||
<ListInfoItem class="list-item" title="Ends At" :content="subscription.data.attributes.ends_at"/>
|
||||
</ListInfo>
|
||||
<div class="plan-action">
|
||||
<ButtonBase
|
||||
:disabled="isResuming"
|
||||
@click.native="resumeSubscription"
|
||||
:button-style="resumeButtonStyle"
|
||||
class="confirm-button">
|
||||
{{ resumeButtonText }}
|
||||
</ButtonBase>
|
||||
</div>
|
||||
</div>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
@@ -65,26 +75,31 @@
|
||||
return this.isConfirmedCancel ? this.$t('popup_share_edit.confirm') : 'Cancel Plan'
|
||||
},
|
||||
cancelButtonStyle() {
|
||||
return this.isConfirmedCancel ? 'danger-solid' : 'danger'
|
||||
return this.isConfirmedCancel ? 'danger-solid' : 'secondary'
|
||||
},
|
||||
subscription() {
|
||||
return this.$store.getters.user.relationships.subscription
|
||||
? this.$store.getters.user.relationships.subscription.data.attributes
|
||||
: undefined
|
||||
resumeButtonText() {
|
||||
return this.isConfirmedResume ? this.$t('popup_share_edit.confirm') : 'Resume Plan'
|
||||
},
|
||||
resumeButtonStyle() {
|
||||
return this.isConfirmedResume ? 'theme-solid' : 'secondary'
|
||||
},
|
||||
status() {
|
||||
if (this.subscription.canceled) {
|
||||
if (this.subscription.data.attributes.canceled) {
|
||||
return 'Canceled'
|
||||
}
|
||||
if (this.subscription.active) {
|
||||
if (this.subscription.data.attributes.active) {
|
||||
return 'Active'
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
subscription: undefined,
|
||||
isConfirmedCancel: false,
|
||||
isConfirmedResume: false,
|
||||
isDeleting: false,
|
||||
isResuming: false,
|
||||
isLoading: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -98,6 +113,7 @@
|
||||
|
||||
// Start deleting spinner button
|
||||
this.isDeleting = true
|
||||
this.isLoading = true
|
||||
|
||||
// Send delete request
|
||||
axios
|
||||
@@ -105,7 +121,9 @@
|
||||
.then(() => {
|
||||
|
||||
// Update user data
|
||||
this.$store.dispatch('getAppData')
|
||||
this.$store.dispatch('getAppData').then(() => {
|
||||
this.fetchSubscriptionDetail()
|
||||
})
|
||||
|
||||
// End deleting spinner button
|
||||
this.isDeleting = false
|
||||
@@ -122,9 +140,61 @@
|
||||
|
||||
// End deleting spinner button
|
||||
this.isDeleting = false
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
resumeSubscription() {
|
||||
|
||||
// Set confirm button
|
||||
if (! this.isConfirmedResume) {
|
||||
|
||||
this.isConfirmedResume = true
|
||||
} else {
|
||||
|
||||
// Start deleting spinner button
|
||||
this.isResuming = true
|
||||
this.isLoading = true
|
||||
|
||||
// Send delete request
|
||||
axios
|
||||
.post('/api/subscription/resume')
|
||||
.then(() => {
|
||||
|
||||
// Update user data
|
||||
this.$store.dispatch('getAppData').then(() => {
|
||||
this.fetchSubscriptionDetail()
|
||||
})
|
||||
|
||||
// End deleting spinner button
|
||||
this.isResuming = false
|
||||
|
||||
events.$emit('alert:open', {
|
||||
emoji: '👍',
|
||||
title: 'Subscription Was Resumed',
|
||||
message: 'Your subscription was re-activated, and they will be billed on the original billing cycle.',
|
||||
buttonStyle: 'theme',
|
||||
button: 'That\'s awesome!'
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
// End deleting spinner button
|
||||
this.isResuming = false
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
fetchSubscriptionDetail() {
|
||||
axios.get('/api/user/subscription')
|
||||
.then(response => {
|
||||
this.subscription = response.data
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchSubscriptionDetail()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -133,7 +203,7 @@
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.cancel-plan {
|
||||
.plan-action {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
4
resources/sass/app.scss
vendored
@@ -50,7 +50,7 @@
|
||||
&.center-page {
|
||||
height: 100%;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 50px;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
.action-icons {
|
||||
white-space: nowrap;
|
||||
|
||||
a {
|
||||
a, .icon {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
<div id="app"></div>
|
||||
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script>
|
||||
let config = {
|
||||
locale: '{{ \Illuminate\Support\Facades\App::getLocale() }}',
|
||||
@@ -35,6 +36,7 @@
|
||||
userRegistration: {{ config('vuefilemanager.registration') ? 1 : 0 }},
|
||||
storageLimit: {{ config('vuefilemanager.limit_storage_by_capacity') ? 1 : 0 }},
|
||||
isSaaS: 1,
|
||||
isDemo: {{ env('APP_DEMO') ? 1 : 0 }},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -56,13 +56,21 @@ Route::group(['middleware' => ['auth:api', 'auth.master', 'scope:master']], func
|
||||
Route::patch('/user/relationships/settings', 'User\AccountController@update_user_settings');
|
||||
Route::post('/user/password', 'User\AccountController@change_password');
|
||||
Route::patch('/user/profile', 'User\AccountController@update_profile');
|
||||
Route::get('/user/subscription', 'User\SubscriptionController@show');
|
||||
Route::get('/user/invoices', 'User\AccountController@invoices');
|
||||
Route::get('/user/storage', 'User\AccountController@storage');
|
||||
Route::get('/user', 'User\AccountController@user');
|
||||
|
||||
// Payment cards
|
||||
Route::delete('/user/payment-cards/{id}', 'User\PaymentCardsController@delete');
|
||||
Route::patch('/user/payment-cards/{id}', 'User\PaymentCardsController@update');
|
||||
Route::get('/user/payments', 'User\PaymentCardsController@payment_methods');
|
||||
|
||||
// Subscription
|
||||
Route::get('/stripe/setup-intent', 'User\SubscriptionController@stripe_setup_intent');
|
||||
Route::post('/subscription/upgrade', 'User\SubscriptionController@upgrade');
|
||||
Route::post('/subscription/cancel', 'User\SubscriptionController@cancel');
|
||||
Route::post('/subscription/resume', 'User\SubscriptionController@resume');
|
||||
|
||||
// Browse
|
||||
Route::get('/participant-uploads', 'FileBrowser\BrowseController@participant_uploads');
|
||||
@@ -112,6 +120,7 @@ Route::group(['middleware' => ['auth:api', 'auth.master', 'auth.admin', 'scope:m
|
||||
Route::get('/gateways', 'Admin\GatewayController@index');
|
||||
Route::get('/gateways/{type}', 'Admin\GatewayController@show');
|
||||
Route::patch('/gateways/{type}', 'Admin\GatewayController@update');
|
||||
Route::get('/gateways/{type}/transactions', 'Admin\GatewayController@show_transactions');
|
||||
|
||||
// Plans
|
||||
Route::get('/plans', 'Admin\PlanController@index');
|
||||
|
||||
@@ -16,59 +16,9 @@ use Rinvex\Subscriptions\Models\PlanFeature;
|
||||
|
||||
Route::get('/debug', function () {
|
||||
|
||||
$user = User::find(1);
|
||||
|
||||
/*
|
||||
* 1. Create plan
|
||||
*/
|
||||
/* $plan = app('rinvex.subscriptions.plan')->create([
|
||||
'name' => 'Starter Pack',
|
||||
'description' => 'The best for start with',
|
||||
'price' => 9.99,
|
||||
'signup_fee' => 0,
|
||||
'invoice_period' => 1,
|
||||
'invoice_interval' => 'month',
|
||||
'trial_period' => 7,
|
||||
'trial_interval' => 'day',
|
||||
'sort_order' => 1,
|
||||
'currency' => 'USD',
|
||||
]);
|
||||
|
||||
// Create multiple plan features at once
|
||||
$plan->features()->saveMany([
|
||||
new PlanFeature(['name' => 'Storage capacity', 'value' => 200, 'sort_order' => 1]),
|
||||
]);
|
||||
|
||||
return $plan;
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2. Get plan
|
||||
*/
|
||||
|
||||
/* $plan = app('rinvex.subscriptions.plan')->find(6);
|
||||
|
||||
return $plan;
|
||||
//return $plan->subscriptions;
|
||||
|
||||
$space = $plan->getFeatureBySlug('storage-capacity')->value;*/
|
||||
|
||||
//return $space;
|
||||
|
||||
/*
|
||||
* 3. Create subscription
|
||||
*/
|
||||
|
||||
$user = Auth::user();
|
||||
//$plan = app('rinvex.subscriptions.plan')->find(6);
|
||||
|
||||
//return $user->activeSubscriptions();
|
||||
|
||||
return $user->subscription('Starter Pack')->cancel();
|
||||
|
||||
//$user->newSubscription('Starter Pack', $plan);
|
||||
|
||||
//return $plan->subscriptions;
|
||||
//return $user->subscribedTo(5);
|
||||
return $user->subscription('main')->asStripeSubscription();
|
||||
});
|
||||
|
||||
// Deployment Webhook URL
|
||||
|
||||