mirror of https://github.com/4xmen/xshop.git
added customer controller
added state and city installed api route added address inputpull/44/head
parent
a20dc80748
commit
62debcbe6d
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class PersianFaker
|
||||
{
|
||||
|
||||
private static $mobile_prefix = ['0912', '0919', '0935', '0936', '0937', '0933', '0938', '0915'];
|
||||
private static $card_prefix = ['6037', '6104', '6391', '6280', '6273', '6287', '6280', '5022'];
|
||||
|
||||
private static $colors = [
|
||||
'red' => ['name' => 'قرمز', 'code' => '#ff0000'],
|
||||
'blue' => ['name' => 'آبی', 'code' => '#0000ff'],
|
||||
'green' => ['name' => 'سبز', 'code' => '#008000'],
|
||||
'yellow' => ['name' => 'زرد', 'code' => '#ffff00'],
|
||||
'purple' => ['name' => 'بنفش', 'code' => '#800080'],
|
||||
'orange' => ['name' => 'نارنجی', 'code' => '#ffa500'],
|
||||
'pink' => ['name' => 'صورتی', 'code' => '#ffc0cb'],
|
||||
'white' => ['name' => 'سفید', 'code' => '#ffffff'],
|
||||
'black' => ['name' => 'سیاه', 'code' => '#000000'],
|
||||
'grey' => ['name' => 'خاکستری', 'code' => '#808080'],
|
||||
'brown' => ['name' => 'قهوهای', 'code' => '#a52a2a'],
|
||||
'silver' => ['name' => 'نقرهای', 'code' => '#c0c0c0'],
|
||||
'gold' => ['name' => 'طلایی', 'code' => '#ffd700'],
|
||||
'turquoise' => ['name' => 'فیروزه ای', 'code' => '#40e0d0'],
|
||||
'magenta' => ['name' => 'بنفش روشن', 'code' => '#ff00ff'],
|
||||
'cyan' => ['name' => 'فیروزی', 'code' => '#00ffff'],
|
||||
'maroon' => ['name' => 'آبی کمرنگ', 'code' => '#800000'],
|
||||
'navy' => ['name' => 'نیرویی', 'code' => '#000080'],
|
||||
'teal' => ['name' => 'نیلی', 'code' => '#008080'],
|
||||
'olive' => ['name' => 'زیتونی', 'code' => '#808000'],
|
||||
];
|
||||
|
||||
static public function mobile()
|
||||
{
|
||||
return self::$mobile_prefix[rand(0, count(self::$mobile_prefix) - 1)] . rand(1000000, 9999999);
|
||||
}
|
||||
|
||||
|
||||
static public function shetabCard()
|
||||
{
|
||||
return self::$card_prefix[rand(0, count(self::$card_prefix) - 1)] . '-'
|
||||
. rand(1000, 9999) . '-' . rand(1000, 9999) . '-' . rand(1000, 9999);
|
||||
}
|
||||
|
||||
|
||||
static function validCodeMeli()
|
||||
{
|
||||
do {
|
||||
$randomNumber = str_pad(mt_rand(1, 99999999), 8, '0', STR_PAD_LEFT);
|
||||
$code = '0000' . $randomNumber;
|
||||
$code = substr($code, strlen($code) - 10, 10);
|
||||
|
||||
if (intval(substr($code, 3, 6)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$checksum = intval(substr($code, 9, 1));
|
||||
$s = 0;
|
||||
for ($i = 0; $i < 9; $i++) {
|
||||
$s += intval(substr($code, $i, 1)) * (10 - $i);
|
||||
}
|
||||
|
||||
$s = $s % 11;
|
||||
|
||||
if (($s < 2 && $checksum == $s) || ($s >= 2 && $checksum == (11 - $s))) {
|
||||
return $code;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
static public function color(){
|
||||
$colors = self::$colors;
|
||||
shuffle($colors);
|
||||
return $colors[0];
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Address;
|
||||
use App\Models\Customer;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AddressController extends Controller
|
||||
{
|
||||
|
||||
public function save(Address $address, Request $request)
|
||||
{
|
||||
$address->address = $request->input('address');
|
||||
$address->lat = $request->input('lat');
|
||||
$address->lng = $request->input('lng');
|
||||
$address->state_id = $request->input('state_id')??null;
|
||||
$address->city_id = $request->input('city_id')??null;
|
||||
$address->zip = $request->input('zip');
|
||||
$address->save();
|
||||
return $address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request, Customer $item)
|
||||
{
|
||||
//
|
||||
|
||||
$request->validate([
|
||||
'address' => ['required', 'string', 'min:10'],
|
||||
'zip' => ['required', 'string', 'min:5'],
|
||||
'state_id' => ['required', 'exists:states,id'],
|
||||
'city_id' => ['required', 'exists:cities,id'],
|
||||
'lat' => ['nullable'],
|
||||
'lng' => ['nullable'],
|
||||
]);
|
||||
|
||||
$address = new Address();
|
||||
$address->customer_id = $item->id;
|
||||
$address = $this->save($address, $request);
|
||||
logAdmin(__METHOD__,Address::class,$address->id);
|
||||
return ['OK' => true,'message' => __("Address added to :CUSTOMER",['CUSTOMER'=>$item->name]), 'list'=> $item->addresses];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(Address $address)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(Address $address)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, Address $item)
|
||||
{
|
||||
//
|
||||
$request->validate([
|
||||
'address' => ['required', 'string', 'min:10'],
|
||||
'zip' => ['required', 'string', 'min:5'],
|
||||
'state_id' => ['required', 'exists:states,id'],
|
||||
'city_id' => ['required', 'exists:cities,id'],
|
||||
'lat' => ['nullable'],
|
||||
'lng' => ['nullable'],
|
||||
]);
|
||||
$this->save($item, $request);
|
||||
logAdmin(__METHOD__,Address::class,$item->id);
|
||||
return ['OK' => true, "message" => __("address updated")];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(Address $item)
|
||||
{
|
||||
//
|
||||
$add = $item->address ;
|
||||
|
||||
logAdmin(__METHOD__,Address::class,$item->id);
|
||||
$item->delete();
|
||||
return ['OK' => true, "message" => __(":ADDRESS removed",['ADDRESS' => $add])];
|
||||
}
|
||||
|
||||
|
||||
public function customer(Customer $item)
|
||||
{
|
||||
return $item->addresses;
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\XController;
|
||||
use App\Http\Requests\CustomerSaveRequest;
|
||||
use App\Models\Access;
|
||||
use App\Models\Customer;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Helper;
|
||||
use function App\Helpers\hasCreateRoute;
|
||||
|
||||
class CustomerController extends XController
|
||||
{
|
||||
|
||||
// protected $_MODEL_ = Customer::class;
|
||||
// protected $SAVE_REQUEST = CustomerSaveRequest::class;
|
||||
|
||||
protected $cols = ['name','mobile','email'];
|
||||
protected $extra_cols = ['id','deleted_at'];
|
||||
|
||||
protected $searchable = ['name','mobile','email'];
|
||||
|
||||
protected $listView = 'admin.customers.customer-list';
|
||||
protected $formView = 'admin.customers.customer-form';
|
||||
|
||||
|
||||
protected $buttons = [
|
||||
'edit' =>
|
||||
['title' => "Edit", 'class' => 'btn-outline-primary', 'icon' => 'ri-edit-2-line'],
|
||||
'show' =>
|
||||
['title' => "Detail", 'class' => 'btn-outline-light', 'icon' => 'ri-eye-line'],
|
||||
'destroy' =>
|
||||
['title' => "Remove", 'class' => 'btn-outline-danger delete-confirm', 'icon' => 'ri-close-line'],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(Customer::class, CustomerSaveRequest::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $customer Customer
|
||||
* @param $request CustomerSaveRequest
|
||||
* @return Customer
|
||||
*/
|
||||
public function save($customer, $request)
|
||||
{
|
||||
|
||||
$customer->name = $request->input('name');
|
||||
$customer->address = $request->input('address');
|
||||
$customer->state = $request->input('state');
|
||||
$customer->credit = $request->input('credit')??0 ;
|
||||
$customer->city = $request->input('city');
|
||||
$customer->postal_code = $request->input('postal_code');
|
||||
if ($request->has('email')) {
|
||||
$customer->email = $request->input('email');
|
||||
}
|
||||
$customer->mobile = $request->input('mobile');
|
||||
$customer->description = $request->input('description');
|
||||
|
||||
if (trim($request->input('password')) != '') {
|
||||
$customer->password = bcrypt($request->input('password'));
|
||||
}
|
||||
$customer->colleague = $request->has('colleague');
|
||||
$customer->save();
|
||||
return $customer;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
return view($this->formView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(Customer $item)
|
||||
{
|
||||
//
|
||||
return view($this->formView, compact('item'));
|
||||
}
|
||||
|
||||
public function bulk(Request $request)
|
||||
{
|
||||
|
||||
// dd($request->all());
|
||||
$data = explode('.', $request->input('action'));
|
||||
$action = $data[0];
|
||||
$ids = $request->input('id');
|
||||
switch ($action) {
|
||||
case 'delete':
|
||||
$msg = __(':COUNT items deleted successfully', ['COUNT' => count($ids)]);
|
||||
$this->_MODEL_::destroy($ids);
|
||||
break;
|
||||
/**restore*/
|
||||
case 'restore':
|
||||
$msg = __(':COUNT items restored successfully', ['COUNT' => count($ids)]);
|
||||
foreach ($ids as $id) {
|
||||
$this->_MODEL_::withTrashed()->find($id)->restore();
|
||||
}
|
||||
break;
|
||||
/*restore**/
|
||||
default:
|
||||
$msg = __('Unknown bulk action : :ACTION', ["ACTION" => $action]);
|
||||
}
|
||||
|
||||
return $this->do_bulk($msg, $action, $ids);
|
||||
}
|
||||
|
||||
public function destroy(Customer $item)
|
||||
{
|
||||
return parent::delete($item);
|
||||
}
|
||||
|
||||
|
||||
public function update(Request $request, Customer $item)
|
||||
{
|
||||
return $this->bringUp($request, $item);
|
||||
}
|
||||
|
||||
|
||||
/**restore*/
|
||||
public function restore($item)
|
||||
{
|
||||
return parent::restoreing(Customer::withTrashed()->where('id', $item)->first());
|
||||
}
|
||||
/*restore**/
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CityCollection;
|
||||
use App\Http\Resources\StateCollection;
|
||||
use App\Models\State;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class StateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
return StateCollection::collection(State::all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(State $state)
|
||||
{
|
||||
//
|
||||
return CityCollection::collection($state->cities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(State $state)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, State $state)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(State $state)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CustomerSaveRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:customers,email'],
|
||||
'password' => ['nullable', 'string', 'min:6', 'confirmed'],
|
||||
'mobile'=> ['required', 'string', 'min:10'],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class CityCollection extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'lat' => $this->lat,
|
||||
'lng' => $this->lng
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class StateCollection extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'country' => $this->country,
|
||||
'lat' => $this->lat,
|
||||
'lng' => $this->lng
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Translatable\HasTranslations;
|
||||
|
||||
class City extends Model
|
||||
{
|
||||
use HasTranslations,SoftDeletes;
|
||||
|
||||
public $translatable = ['name'];
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Translatable\HasTranslations;
|
||||
|
||||
class State extends Model
|
||||
{
|
||||
use HasFactory,HasTranslations,SoftDeletes;
|
||||
|
||||
public $translatable = ['name', 'country'];
|
||||
|
||||
public function cities(){
|
||||
return $this->hasMany(City::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stateful Domains
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Requests from the following domains / hosts will receive stateful API
|
||||
| authentication cookies. Typically, these should include your local
|
||||
| and production domains which access your API via a frontend SPA.
|
||||
|
|
||||
*/
|
||||
|
||||
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
||||
'%s%s',
|
||||
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
||||
Sanctum::currentApplicationUrlWithPort()
|
||||
))),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sanctum Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array contains the authentication guards that will be checked when
|
||||
| Sanctum is trying to authenticate a request. If none of these guards
|
||||
| are able to authenticate the request, Sanctum will use the bearer
|
||||
| token that's present on an incoming request for authentication.
|
||||
|
|
||||
*/
|
||||
|
||||
'guard' => ['web'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expiration Minutes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value controls the number of minutes until an issued token will be
|
||||
| considered expired. This will override any values set in the token's
|
||||
| "expires_at" attribute, but first-party sessions are not affected.
|
||||
|
|
||||
*/
|
||||
|
||||
'expiration' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Token Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Sanctum can prefix new tokens in order to take advantage of numerous
|
||||
| security scanning initiatives maintained by open source platforms
|
||||
| that notify developers if they commit tokens into repositories.
|
||||
|
|
||||
| See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
|
||||
|
|
||||
*/
|
||||
|
||||
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sanctum Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When authenticating your first-party SPA with Sanctum you may need to
|
||||
| customize some of the middleware Sanctum uses while processing the
|
||||
| request. You may change the middleware listed below as required.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => [
|
||||
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
|
||||
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
|
||||
'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
|
||||
],
|
||||
|
||||
];
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\State>
|
||||
*/
|
||||
class StateFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('states', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->text('name');
|
||||
$table->double('lat');
|
||||
$table->double('lng');
|
||||
$table->text('country');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('states');
|
||||
}
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('cities', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->text('name');
|
||||
$table->double('lat')->nullable();
|
||||
$table->double('lng')->nullable();
|
||||
$table->unsignedBigInteger('state_id');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('cities');
|
||||
}
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('tokenable');
|
||||
$table->string('name');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->text('abilities')->nullable();
|
||||
$table->timestamp('last_used_at')->nullable();
|
||||
$table->timestamp('expires_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('personal_access_tokens');
|
||||
}
|
||||
};
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,872 @@
|
||||
{
|
||||
"name": "xshop2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"remixicon": "^4.2.0",
|
||||
"three": "0.150.0",
|
||||
"vazirmatn": "^33.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@vitejs/plugin-vue": "^4.5.0",
|
||||
"axios": "^1.6.4",
|
||||
"bootstrap": "^5.2.3",
|
||||
"laravel-vite-plugin": "^1.0",
|
||||
"sass": "^1.56.1",
|
||||
"vite": "^5.0",
|
||||
"vue": "^3.2.37"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.24.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz",
|
||||
"integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
|
||||
"integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
|
||||
"integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
|
||||
"integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vitejs/plugin-vue": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz",
|
||||
"integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^4.0.0 || ^5.0.0",
|
||||
"vue": "^3.2.25"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.26.tgz",
|
||||
"integrity": "sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.24.4",
|
||||
"@vue/shared": "3.4.26",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.26.tgz",
|
||||
"integrity": "sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.4.26",
|
||||
"@vue/shared": "3.4.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.26.tgz",
|
||||
"integrity": "sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.24.4",
|
||||
"@vue/compiler-core": "3.4.26",
|
||||
"@vue/compiler-dom": "3.4.26",
|
||||
"@vue/compiler-ssr": "3.4.26",
|
||||
"@vue/shared": "3.4.26",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.10",
|
||||
"postcss": "^8.4.38",
|
||||
"source-map-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.26.tgz",
|
||||
"integrity": "sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.26",
|
||||
"@vue/shared": "3.4.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.26.tgz",
|
||||
"integrity": "sha512-E/ynEAu/pw0yotJeLdvZEsp5Olmxt+9/WqzvKff0gE67tw73gmbx6tRkiagE/eH0UCubzSlGRebCbidB1CpqZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.4.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.26.tgz",
|
||||
"integrity": "sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.26",
|
||||
"@vue/shared": "3.4.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.26.tgz",
|
||||
"integrity": "sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/runtime-core": "3.4.26",
|
||||
"@vue/shared": "3.4.26",
|
||||
"csstype": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.26.tgz",
|
||||
"integrity": "sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.4.26",
|
||||
"@vue/shared": "3.4.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.4.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.26.tgz",
|
||||
"integrity": "sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.8",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
|
||||
"integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
|
||||
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.11.8"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
||||
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.20.2",
|
||||
"@esbuild/android-arm": "0.20.2",
|
||||
"@esbuild/android-arm64": "0.20.2",
|
||||
"@esbuild/android-x64": "0.20.2",
|
||||
"@esbuild/darwin-arm64": "0.20.2",
|
||||
"@esbuild/darwin-x64": "0.20.2",
|
||||
"@esbuild/freebsd-arm64": "0.20.2",
|
||||
"@esbuild/freebsd-x64": "0.20.2",
|
||||
"@esbuild/linux-arm": "0.20.2",
|
||||
"@esbuild/linux-arm64": "0.20.2",
|
||||
"@esbuild/linux-ia32": "0.20.2",
|
||||
"@esbuild/linux-loong64": "0.20.2",
|
||||
"@esbuild/linux-mips64el": "0.20.2",
|
||||
"@esbuild/linux-ppc64": "0.20.2",
|
||||
"@esbuild/linux-riscv64": "0.20.2",
|
||||
"@esbuild/linux-s390x": "0.20.2",
|
||||
"@esbuild/linux-x64": "0.20.2",
|
||||
"@esbuild/netbsd-x64": "0.20.2",
|
||||
"@esbuild/openbsd-x64": "0.20.2",
|
||||
"@esbuild/sunos-x64": "0.20.2",
|
||||
"@esbuild/win32-arm64": "0.20.2",
|
||||
"@esbuild/win32-ia32": "0.20.2",
|
||||
"@esbuild/win32-x64": "0.20.2"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
|
||||
"integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/laravel-vite-plugin": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.2.tgz",
|
||||
"integrity": "sha512-Mcclml10khYzBVxDwJro8wnVDwD4i7XOSEMACQNnarvTnHjrjXLLL+B/Snif2wYAyElsOqagJZ7VAinb/2vF5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"picocolors": "^1.0.0",
|
||||
"vite-plugin-full-reload": "^1.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"clean-orphaned-assets": "bin/clean.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.10",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
||||
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.38",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
|
||||
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/remixicon": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/remixicon/-/remixicon-4.2.0.tgz",
|
||||
"integrity": "sha512-MF5wApNveRh3n0iMVM+lr2nSWrj/rBbSD2eWapuD9ReYRGs5naAUR1BqVBCHGqm286FIS6zwwmUf96QjHQ9l4w==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
|
||||
"integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.17.2",
|
||||
"@rollup/rollup-android-arm64": "4.17.2",
|
||||
"@rollup/rollup-darwin-arm64": "4.17.2",
|
||||
"@rollup/rollup-darwin-x64": "4.17.2",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.17.2",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.17.2",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.17.2",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.17.2",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.17.2",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.17.2",
|
||||
"@rollup/rollup-linux-x64-musl": "4.17.2",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.17.2",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.17.2",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.17.2",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.76.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.76.0.tgz",
|
||||
"integrity": "sha512-nc3LeqvF2FNW5xGF1zxZifdW3ffIz5aBb7I7tSvOoNu7z1RQ6pFt9MBuiPtjgaI62YWrM/txjWlOCFiGtf2xpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/three": {
|
||||
"version": "0.150.0",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.150.0.tgz",
|
||||
"integrity": "sha512-12oqqBZom9fb5HtX3rD8qPVnamojuiN5Os7r0x8s3HQ+WHRwnEyzl2XU3aEKocsDkG++rkE9+HWzx77O59NXtw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vazirmatn": {
|
||||
"version": "33.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vazirmatn/-/vazirmatn-33.0.3.tgz",
|
||||
"integrity": "sha512-fbjNc0CMjazZpIegWzz9OHGzI1APFboT+x7ZecXlUCtDe/nkyx7gtCTZnWS/+eeXG7fbfXymCPKJI8EsnM3iqw==",
|
||||
"license": "OFL"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.2.11",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
|
||||
"integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.20.1",
|
||||
"postcss": "^8.4.38",
|
||||
"rollup": "^4.13.0"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vitejs/vite?sponsor=1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "^18.0.0 || >=20.0.0",
|
||||
"less": "*",
|
||||
"lightningcss": "^1.21.0",
|
||||
"sass": "*",
|
||||
"stylus": "*",
|
||||
"sugarss": "*",
|
||||
"terser": "^5.4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
},
|
||||
"less": {
|
||||
"optional": true
|
||||
},
|
||||
"lightningcss": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
},
|
||||
"stylus": {
|
||||
"optional": true
|
||||
},
|
||||
"sugarss": {
|
||||
"optional": true
|
||||
},
|
||||
"terser": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-full-reload": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.1.0.tgz",
|
||||
"integrity": "sha512-3cObNDzX6DdfhD9E7kf6w2mNunFpD7drxyNgHLw+XwIYAgb+Xt16SEXo0Up4VH+TMf3n+DSVJZtW2POBGcBYAA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"picocolors": "^1.0.0",
|
||||
"picomatch": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.4.26",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.26.tgz",
|
||||
"integrity": "sha512-bUIq/p+VB+0xrJubaemrfhk1/FiW9iX+pDV+62I/XJ6EkspAO9/DXEjbDFoe8pIfOZBqfk45i9BMc41ptP/uRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.26",
|
||||
"@vue/compiler-sfc": "3.4.26",
|
||||
"@vue/runtime-dom": "3.4.26",
|
||||
"@vue/server-renderer": "3.4.26",
|
||||
"@vue/shared": "3.4.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,424 @@
|
||||
<template>
|
||||
<div id="address-input">
|
||||
|
||||
<table class="w-100">
|
||||
<tr v-for="ad in addresses">
|
||||
<td>
|
||||
{{ ad.address }}
|
||||
</td>
|
||||
<td class="py-1">
|
||||
<div class="btn btn-outline-danger btn-sm float-end mx-2" @click="removing(ad.id)">
|
||||
<i class="ri-close-line"></i>
|
||||
</div>
|
||||
<div class="btn btn-outline-primary btn-sm float-end" @click="editing(ad)">
|
||||
<i class="ri-edit-2-line"></i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" @click="adding">
|
||||
<i class="ri-add-line"></i>
|
||||
</button>
|
||||
|
||||
<div id="address-modal" v-if="modal" @click.self="modal = false">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Address editor <!-- WIP Translate -->
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="st">
|
||||
State: <!-- WIP Translate -->
|
||||
</label>
|
||||
<select @change="updateState" class="form-control" v-model="state_id" id="st">
|
||||
<option :data-lat="s.lat" :data-lng="s.lng" :value="s.id" v-for="s in states">
|
||||
{{ s.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="st">
|
||||
City: <!-- WIP Translate -->
|
||||
</label>
|
||||
<select @change="updateCity" class="form-control" v-model="city_id" id="st">
|
||||
<option :value="c.id" v-for="c in cities"> {{ c.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 my-3">
|
||||
<div ref="mapContainer" :style="'height: 300px;'+mapStyle"></div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<textarea rows="2" class="form-control" placeholder="Address" v-model="address"></textarea>
|
||||
<!-- WIP Translate -->
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="zip">
|
||||
Postcode: <!-- WIP Translate -->
|
||||
</label>
|
||||
<input type="text" class="form-control" v-model="zip">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button class="btn btn-primary w-100" type="button" @click="save">
|
||||
<i class="ri-save-2-line"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import {useToast} from 'vue-toast-notification';
|
||||
|
||||
const $toast = useToast();
|
||||
|
||||
export default {
|
||||
name: "address-input",
|
||||
components: {},
|
||||
data: () => {
|
||||
return {
|
||||
id: null,
|
||||
action: 'add',
|
||||
modal: false,
|
||||
addresses: [],
|
||||
states: [],
|
||||
cities: [],
|
||||
state_id: null,
|
||||
city_id: null,
|
||||
map: null,
|
||||
marker: null,
|
||||
zoom: 10,
|
||||
address: '',
|
||||
zip: '',
|
||||
lat: null,
|
||||
lng: null,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
listLink: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
addLink: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
updateLink: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
remLink: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
stateLink: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
citiesLink: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
darkMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
let res = await axios.get(this.stateLink);
|
||||
this.states = res.data.data;
|
||||
// console.log(res.data);
|
||||
} catch (e) {
|
||||
$toast.error(e.message);
|
||||
}
|
||||
await this.updateList();
|
||||
// await this.initMap();
|
||||
// if (this.states[0].lat != null && this.states[0].lng != null){
|
||||
// this.changeMapCenter(this.states[0].lat,this.states[0].lng)
|
||||
// }
|
||||
},
|
||||
computed: {
|
||||
mapStyle() {
|
||||
if (this.darkMode) {
|
||||
return 'filter: invert(100%) hue-rotate(120deg) brightness(95%) contrast(90%);';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async save() {
|
||||
let canSave = true;
|
||||
if (this.state_id == null) {
|
||||
$toast.error("State is required"); // WIP translate
|
||||
canSave = false;
|
||||
}
|
||||
if (this.city_id == null) {
|
||||
$toast.error("City is required"); // WIP translate
|
||||
canSave = false;
|
||||
}
|
||||
if (this.address.length < 10) {
|
||||
$toast.error("Address is required"); // WIP translate
|
||||
canSave = false;
|
||||
}
|
||||
if (this.zip.length < 5) {
|
||||
$toast.error("Post code is required"); // WIP translate
|
||||
canSave = false;
|
||||
}
|
||||
if (!canSave) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.action == 'add') {
|
||||
|
||||
let data = {
|
||||
address: this.address,
|
||||
state_id: this.state_id,
|
||||
city_id: this.city_id,
|
||||
zip: this.zip,
|
||||
lat: this.lat,
|
||||
lng: this.lng
|
||||
};
|
||||
try {
|
||||
let r = await axios.post(this.addLink, data);
|
||||
if (r.data.OK) {
|
||||
this.addresses = r.data.list;
|
||||
$toast.success(r.data.message);
|
||||
this.modal = false;
|
||||
}
|
||||
} catch (e) {
|
||||
$toast.error('err!' + e.message);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
let data = {
|
||||
address: this.address,
|
||||
state_id: this.state_id,
|
||||
city_id: this.city_id,
|
||||
zip: this.zip,
|
||||
lat: this.lat,
|
||||
lng: this.lng
|
||||
};
|
||||
try {
|
||||
const url = this.updateLink + '/' + this.id;
|
||||
let r = await axios.post(url, data);
|
||||
if (r.data.OK) {
|
||||
$toast.success(r.data.message);
|
||||
await this.updateList();
|
||||
this.modal = false;
|
||||
}
|
||||
} catch (e) {
|
||||
$toast.error('err!' + e.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
showModal() {
|
||||
|
||||
this.modal = true;
|
||||
setTimeout(() => {
|
||||
this.initMap();
|
||||
}, 50);
|
||||
},
|
||||
async removing(id) {
|
||||
if (!confirm('Sure?')) { //WIP: translate
|
||||
return;
|
||||
}
|
||||
|
||||
const url = this.remLink + '/' + id;
|
||||
try {
|
||||
let r = await axios.get(url);
|
||||
if (r.data.OK) {
|
||||
$toast.success(r.data.message);
|
||||
this.updateList();
|
||||
}
|
||||
} catch(e) {
|
||||
$toast.error('err!' + e.message);
|
||||
}
|
||||
},
|
||||
async editing(dt) {
|
||||
this.showModal();
|
||||
this.action = 'edit';
|
||||
this.id = dt.id;
|
||||
this.lat = dt.lat;
|
||||
this.lng = dt.lng;
|
||||
this.zip = dt.zip;
|
||||
this.address = dt.address;
|
||||
this.state_id = dt.state_id;
|
||||
await this.updateState();
|
||||
this.city_id = dt.city_id;
|
||||
if (this.lng != null && this.lat != null) {
|
||||
this.zoom = 16;
|
||||
setTimeout(() => {
|
||||
this.changeMapCenter(this.lat, this.lng);
|
||||
this.marker = L.marker({lat:this.lat, lng: this.lng}).addTo(this.map);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
},
|
||||
adding() {
|
||||
this.action = 'add';
|
||||
this.address = '';
|
||||
this.zip = '';
|
||||
this.state_id = null;
|
||||
this.showModal();
|
||||
|
||||
},
|
||||
initMap() {
|
||||
this.map = L.map(this.$refs.mapContainer).setView([35.83266000, 50.99155000], 10);
|
||||
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© openstreetmap',
|
||||
attributionControl: false,
|
||||
}).addTo(this.map);
|
||||
|
||||
this.map.on('click', this.onMapClick);
|
||||
this.map.attributionControl.setPrefix('xShop');
|
||||
|
||||
},
|
||||
onMapClick(e) {
|
||||
if (this.marker) {
|
||||
this.map.removeLayer(this.marker);
|
||||
}
|
||||
|
||||
this.marker = L.marker(e.latlng).addTo(this.map);
|
||||
// You can emit the selected location or perform any other desired action here
|
||||
// console.log('Selected location:', e.latlng);
|
||||
this.getAddress(e.latlng);
|
||||
this.lat = e.latlng.lat;
|
||||
this.lng = e.latlng.lng;
|
||||
},
|
||||
changeMapCenter(lat, lng) {
|
||||
try {
|
||||
|
||||
this.map.setView([lat, lng], this.zoom);
|
||||
} catch (e) {
|
||||
// console.log(e.message);
|
||||
setTimeout(() => {
|
||||
console.log('repeat');
|
||||
this.changeMapCenter(lat, lng);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// Change the map center to [40.7128, -74.0059] (New York City) with zoom level 12
|
||||
|
||||
},
|
||||
async updateList() {
|
||||
try {
|
||||
let res = await axios.get(this.listLink);
|
||||
this.addresses = res.data;
|
||||
} catch (e) {
|
||||
$toast.error('err!' + e.message);
|
||||
}
|
||||
},
|
||||
async updateState() {
|
||||
for (const st of this.states) {
|
||||
if (st.id == this.state_id) {
|
||||
// console.log(st);
|
||||
if (st.lat != null && st.lng != null) {
|
||||
this.zoom = 10;
|
||||
this.changeMapCenter(st.lat, st.lng)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let res = await axios.get(this.citiesLink + '/' + this.state_id);
|
||||
this.cities = res.data.data;
|
||||
} catch (e) {
|
||||
$toast.error('err!' + e.message);
|
||||
}
|
||||
},
|
||||
async updateCity() {
|
||||
for (const c of this.cities) {
|
||||
if (c.id == this.city_id) {
|
||||
if (c.lat != null && c.lng != null) {
|
||||
this.zoom = 12;
|
||||
this.changeMapCenter(c.lat, c.lng)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
getAddress(latlng) {
|
||||
const url = `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${latlng.lat}&lon=${latlng.lng}&addressdetails=1&accept-language=en`;
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const address = this.formatAddress(data.address);
|
||||
this.address = address;
|
||||
})
|
||||
.catch(error => {
|
||||
$toast.error('err!' + error.message);
|
||||
});
|
||||
|
||||
},
|
||||
formatAddress(addressData) {
|
||||
|
||||
let formattedAddress = '';
|
||||
|
||||
if (addressData.road) {
|
||||
formattedAddress += addressData.road;
|
||||
}
|
||||
if (addressData.neighbourhood) {
|
||||
formattedAddress += addressData.neighbourhood;
|
||||
}
|
||||
//
|
||||
// if (addressData.house_number) {
|
||||
// formattedAddress += ` ${addressData.house_number}`;
|
||||
// }
|
||||
//
|
||||
if (addressData.postcode) {
|
||||
// formattedAddress += `, ${addressData.postcode}`;
|
||||
let x = addressData.postcode.split('-');
|
||||
this.zip = x.join('');
|
||||
}
|
||||
|
||||
if (addressData.city) {
|
||||
formattedAddress += `, ${addressData.city}`;
|
||||
}
|
||||
//
|
||||
// if (addressData.country) {
|
||||
// formattedAddress += `, ${addressData.country}`;
|
||||
// }
|
||||
|
||||
return formattedAddress;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#address-input {
|
||||
padding: 0 .75rem 1rem;
|
||||
}
|
||||
|
||||
#address-modal {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
backdrop-filter: blur(4px);
|
||||
background: #ffffff33;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#address-modal .card {
|
||||
max-width: 900px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
@ -0,0 +1,147 @@
|
||||
@extends('admin.templates.panel-form-template')
|
||||
@section('title')
|
||||
@if(isset($item))
|
||||
{{__("Edit customer")}} [{{$item->name}}]
|
||||
@else
|
||||
{{__("Add new customer")}}
|
||||
@endif -
|
||||
@endsection
|
||||
@section('form')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
|
||||
@include('components.err')
|
||||
<div class="item-list mb-3">
|
||||
<h3 class="p-3">
|
||||
<i class="ri-message-3-line"></i>
|
||||
{{__("Tips")}}
|
||||
</h3>
|
||||
<ul>
|
||||
<li>
|
||||
{{__("Recommends")}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@if(isset($item))
|
||||
<div class="item-list mb-3">
|
||||
<h3 class="p-3">
|
||||
<i class="ri-user-location-line"></i>
|
||||
{{__("Addresses")}}
|
||||
</h3>
|
||||
<address-input
|
||||
list-link="{{route('admin.address.customer',$item->id)}}"
|
||||
add-link="{{route('admin.address.store',$item->id)}}"
|
||||
update-link="{{route('admin.address.update','')}}"
|
||||
rem-link="{{route('admin.address.destroy','')}}"
|
||||
state-link="{{route('v1.state.index')}}"
|
||||
cities-link="{{route('v1.state.show','')}}"
|
||||
:dark-mode="true"
|
||||
></address-input>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="col-lg-9 ps-xl-1 ps-xxl-1">
|
||||
<div class="general-form ">
|
||||
<h1>
|
||||
@if(isset($item))
|
||||
{{__("Edit customer")}} [{{$item->name}}]
|
||||
@else
|
||||
{{__("Add new customer")}}
|
||||
@endif
|
||||
</h1>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="name">
|
||||
{{__('Name')}}
|
||||
</label>
|
||||
<input name="name" type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
placeholder="{{__('Name')}}" value="{{old('name',$item->name??null)}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="email">
|
||||
{{__('Email')}}
|
||||
</label>
|
||||
<input name="email" type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
placeholder="{{__('Email')}}" value="{{old('email',$item->email??null)}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="credit">
|
||||
{{__('Credit')}}
|
||||
</label>
|
||||
<currency-input :xvalue="{{old('credit',$item->credit??0)}}"
|
||||
name="credit" xid="credit"
|
||||
@error('credit') :err="true" @enderror>
|
||||
</currency-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="mobile">
|
||||
{{__('Mobile')}}
|
||||
</label>
|
||||
<input name="mobile" type="text" class="form-control @error('mobile') is-invalid @enderror"
|
||||
placeholder="{{__('Mobile')}}" value="{{old('mobile',$item->mobile??null)}}"
|
||||
min-length="10"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="password">
|
||||
{{__('Password')}}
|
||||
</label>
|
||||
<input name="password" type="password"
|
||||
class="form-control @error('password') is-invalid @enderror"
|
||||
placeholder="{{__('Password')}}" value="{{old('password',''??null)}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="password_confirmation">
|
||||
{{__('password repeat')}}
|
||||
</label>
|
||||
<input name="password_confirmation" type="password"
|
||||
class="form-control @error('password_confirmation') is-invalid @enderror"
|
||||
placeholder="{{__('password repeat')}}"
|
||||
value="{{old('password_confirmation',$item->password_confirmation??null)}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 mt-3">
|
||||
|
||||
<div class="form-check form-switch pt-4 mt-2">
|
||||
|
||||
<input class="form-check-input @error('colleague') is-invalid @enderror"
|
||||
type="checkbox" id="colleague" name="colleague"
|
||||
@if (isset($item) && $item->colleague)
|
||||
checked
|
||||
@endif>
|
||||
<label class="form-check-label" for="colleague">{{__("Colleague")}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="description">
|
||||
{{__('Description')}}
|
||||
</label>
|
||||
<textarea name="description" id="description" type="password"
|
||||
class="form-control @error('description') is-invalid @enderror"
|
||||
placeholder="{{__('Description')}}">{{old('description',$item->description??null)}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label> </label>
|
||||
<input name="" type="submit" class="btn btn-primary mt-2" value="{{__('Save')}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@ -0,0 +1,15 @@
|
||||
@extends('admin.templates.panel-list-template')
|
||||
|
||||
@section('list-title')
|
||||
<i class="ri-user-3-line"></i>
|
||||
{{__("Customers list")}}
|
||||
@endsection
|
||||
@section('title')
|
||||
{{__("Customers list")}} -
|
||||
@endsection
|
||||
@section('filter')
|
||||
{{-- Other filters --}}
|
||||
@endsection
|
||||
@section('bulk')
|
||||
{{-- <option value="-"> - </option> --}}
|
||||
@endsection
|
@ -1,6 +1,7 @@
|
||||
@yield('js-content')
|
||||
<script type="text/javascript">
|
||||
var xupload = "{{route('admin.ckeditor.upload', ['_token' => csrf_token() ])}}";
|
||||
window.routesList = @json(getAdminRoutes());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
})->middleware('auth:sanctum');
|
||||
|
||||
|
||||
Route::get('', function () {
|
||||
return 'xshop api:'.config('app.name');
|
||||
});
|
||||
|
||||
Route::get('/clear', function () {
|
||||
|
||||
if (!auth()->check()){
|
||||
return abort(403);
|
||||
}
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
Artisan::call('view:clear');
|
||||
Artisan::call('route:clear');
|
||||
return "Cleared!";
|
||||
|
||||
});
|
||||
|
||||
|
||||
Route::prefix('v1')->name('v1.')->group(
|
||||
function () {
|
||||
Route::get('', function () {
|
||||
return 'xShop api v1';
|
||||
});
|
||||
|
||||
Route::get('states', [\App\Http\Controllers\Api\StateController::class,'index'])->name('state.index');
|
||||
Route::get('state/{state}', [\App\Http\Controllers\Api\StateController::class,'show'])->name('state.show');
|
||||
});
|
Loading…
Reference in New Issue