diff --git a/composer.json b/composer.json index 0a58b0e6c..cc67bf6ff 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,8 @@ "webkul/laravel-product": "self.version", "webkul/laravel-shop": "self.version", "webkul/laravel-theme": "self.version", - "webkul/laravel-shipping": "self.version" + "webkul/laravel-shipping": "self.version", + "webkul/laravel-payment": "self.version" }, "autoload": { "classmap": [ @@ -61,7 +62,8 @@ "Webkul\\Inventory\\": "packages/Webkul/Inventory/src", "Webkul\\Product\\": "packages/Webkul/Product/src", "Webkul\\Theme\\": "packages/Webkul/Theme/src", - "Webkul\\Shipping\\": "packages/Webkul/Shipping/src" + "Webkul\\Shipping\\": "packages/Webkul/Shipping/src", + "Webkul\\Payment\\": "packages/Webkul/Payment/src" } }, "autoload-dev": { diff --git a/config/app.php b/config/app.php index ee3b79402..155e3325f 100644 --- a/config/app.php +++ b/config/app.php @@ -192,6 +192,7 @@ return [ Webkul\Theme\Providers\ThemeServiceProvider::class, Webkul\Cart\Providers\CartServiceProvider::class, Webkul\Shipping\Providers\ShippingServiceProvider::class, + Webkul\Payment\Providers\PaymentServiceProvider::class, ], /* diff --git a/config/carriers.php b/config/carriers.php index 87ef4edc0..f088f4172 100644 --- a/config/carriers.php +++ b/config/carriers.php @@ -5,12 +5,9 @@ return [ 'code' => 'flatrate', 'title' => 'Flatrate', 'description' => 'This is a flat rate', - 'status' => '1', + 'active' => true, 'default_rate' => '10', - 'type' => [ - 'per_unit' => 'Per Unit', - 'per order' => 'Per Order', - ], + 'type' => 'per_unit', 'class' => 'Webkul\Shipping\Carriers\FlatRate', ] ]; diff --git a/config/paymentmethods.php b/config/paymentmethods.php new file mode 100644 index 000000000..9b63a0c10 --- /dev/null +++ b/config/paymentmethods.php @@ -0,0 +1,13 @@ + [ + 'code' => 'cashondelivery', + 'title' => 'Cash On Delivery', + 'class' => 'Webkul\Payment\Payment\Payment', + 'order_status' => 'Pending', + 'active' => true + ] +]; + +?> \ No newline at end of file diff --git a/packages/Webkul/Admin/src/Http/routes.php b/packages/Webkul/Admin/src/Http/routes.php index a98ff0be2..2ad586cb1 100644 --- a/packages/Webkul/Admin/src/Http/routes.php +++ b/packages/Webkul/Admin/src/Http/routes.php @@ -49,7 +49,7 @@ Route::group(['middleware' => ['web']], function () { 'view' => 'admin::customers.orders.index' ])->name('admin.customer.orders.index'); - Route::get('customer/reviews', 'Webkul\Shop\Http\Controllers\ReviewController@index')->defaults('_config',[ + Route::get('customer/reviews', 'Webkul\Product\Http\Controllers\ReviewController@index')->defaults('_config',[ 'view' => 'admin::customers.review.index' ])->name('admin.customer.review.index'); @@ -61,11 +61,11 @@ Route::group(['middleware' => ['web']], function () { 'redirect' => 'admin.customer.index' ])->name('admin.customer.store'); - Route::get('customer/reviews/edit/{id}', 'Webkul\Shop\Http\Controllers\ReviewController@edit')->defaults('_config',[ + Route::get('customer/reviews/edit/{id}', 'Webkul\Product\Http\Controllers\ReviewController@edit')->defaults('_config',[ 'view' => 'admin::customers.review.edit' ])->name('admin.customer.review.edit'); - Route::put('customer/reviews/edit/{id}', 'Webkul\Shop\Http\Controllers\ReviewController@update')->defaults('_config', [ + Route::put('customer/reviews/edit/{id}', 'Webkul\Product\Http\Controllers\ReviewController@update')->defaults('_config', [ 'redirect' => 'admin.customer.review.index' ])->name('admin.customer.review.update'); @@ -73,9 +73,9 @@ Route::group(['middleware' => ['web']], function () { 'view' => 'admin::customers.edit' ])->name('admin.customer.edit'); - Route::put('customer/reviews/edit/{id}', 'Webkul\Core\Http\Controllers\CustomerController@update')->defaults('_config', [ - 'redirect' => 'admin.customer.index' - ])->name('admin.customer.update'); + // Route::put('customer/reviews/edit/{id}', 'Webkul\Core\Http\Controllers\CustomerController@update')->defaults('_config', [ + // 'redirect' => 'admin.customer.index' + // ])->name('admin.customer.update'); // dummy number i.e-1 is used for creating view only diff --git a/packages/Webkul/Admin/src/Providers/EventServiceProvider.php b/packages/Webkul/Admin/src/Providers/EventServiceProvider.php index accef9ceb..599550acd 100644 --- a/packages/Webkul/Admin/src/Providers/EventServiceProvider.php +++ b/packages/Webkul/Admin/src/Providers/EventServiceProvider.php @@ -113,7 +113,7 @@ class EventServiceProvider extends ServiceProvider $acl->add('catalog.products', 'Products', 'admin.catalog.products.index', 1); $acl->add('catalog.categories', 'Categories', 'admin.catalog.categories.index', 1); - + $acl->add('configuration', 'Configure', 'admin.account.edit', 5); $acl->add('settings', 'Settings', 'admin.users.index', 6); diff --git a/packages/Webkul/Admin/src/Resources/views/customers/review/edit.blade.php b/packages/Webkul/Admin/src/Resources/views/customers/review/edit.blade.php index d51814fbf..d2ad88652 100644 --- a/packages/Webkul/Admin/src/Resources/views/customers/review/edit.blade.php +++ b/packages/Webkul/Admin/src/Resources/views/customers/review/edit.blade.php @@ -45,11 +45,11 @@
diff --git a/packages/Webkul/Cart/src/Cart.php b/packages/Webkul/Cart/src/Cart.php index a580a8789..aececafae 100644 --- a/packages/Webkul/Cart/src/Cart.php +++ b/packages/Webkul/Cart/src/Cart.php @@ -6,7 +6,7 @@ use Carbon\Carbon; //Cart repositories use Webkul\Cart\Repositories\CartRepository; -use Webkul\Cart\Repositories\CartProductRepository; +use Webkul\Cart\Repositories\CartItemRepository; //Customer repositories use Webkul\Customer\Repositories\CustomerRepository; @@ -14,9 +14,9 @@ use Webkul\Customer\Repositories\CustomerRepository; use Cookie; /** - * Cart facade for all + * Facade for all * the methods to be - * implemented for Cart. + * implemented in Cart. * * @author Prashant Singh * @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com) @@ -24,67 +24,74 @@ use Cookie; class Cart { - protected $_config; - protected $cart; - protected $cartProduct; + protected $cartItem; protected $customer; //Cookie expiry limit in minutes - protected $minutes = 150; + protected $minutes; - public function __construct(CartRepository $cart, CartProductRepository $cartProduct, CustomerRepository $customer ,$minutes = 150) { + public function __construct(CartRepository $cart, CartItemRepository $cartItem, CustomerRepository $customer, $minutes = 150) { $this->customer = $customer; $this->cart = $cart; - $this->cartProduct = $cartProduct; + $this->cartItem = $cartItem; $this->minutes = $minutes; } - public function guestUnitAdd($id) { + public function guestUnitAdd($id, $data) { - //empty array for storing the products + //empty array for storing the products. $products = array(); if(Cookie::has('cart_session_id')) { - //getting the cart session id from cookie + //getting the cart session id from cookie. $cart_session_id = Cookie::get('cart_session_id'); //finding current cart instance in the database table. $current_cart = $this->cart->findOneByField('session_id', $cart_session_id); - //check there is any cart or not + //check there is any cart or not. if(isset($current_cart)) { $current_cart_id = $current_cart['id'] ?? $current_cart->id; $current_cart_session_id = $current_cart['session_id'] ?? $current_cart->session_id; } else { - //if someone deleted then take the flow to the normal + //if someone deleted handle flow to the normal. $this->repairCart($cart_session_id, $id); } - //matching the session id present in the cookie and database are same or not. + //Matching the session id present in the cookie and database are same or not. if((session()->get('cart_session_id') == Cookie::get('cart_session_id')) && ($current_cart_session_id == session()->get('cart_session_id'))) { + $current_cart_items = $this->cart->items($current_cart_id); + $current_cart_products = array(); - $current_cart_products = $this->cart->getProducts($current_cart_id); + foreach($current_cart_items as $current_cart_item) { + array_push($current_cart_products, $this->cartItem->getProduct($current_cart_item->id)); + } //checking new product coming in the cart is new or previously added item. foreach($current_cart_products as $key => $value) { - - $product_id = $value['id'] ?? $value->id; + $product_id = $value; if($product_id == $id) { - //create status code to communicate with session flash + //create status code to communicate with session flash. + $cartItemId = $this->cartItem->findOneByField('product_id', $id)->id; + + $cartItemQuantity = $this->cartItem->findOneByField('product_id', $id)->quantity; + + $this->cartItem->update(['quantity' => $cartItemQuantity + $data['quantity']], $cartItemId); + session()->flash('error', 'Item Already In Cart'); - //remove this its temporary + //remove this its temporary. dump('Item Already In Cart'); return redirect()->back(); @@ -92,29 +99,27 @@ class Cart { } //cart data being attached to the instace. - $cart_data = $this->cart->attach($current_cart_id, $id, 1); + $cart_data = $this->cart->attach($current_cart_id, $id, $data['quantity'], $data['price']); - //getting the products after being attached to cart instance - $cart_products = $this->cart->getProducts($current_cart_id); + //getting the products after being attached to cart instance. + $cart_products = $this->cart->items($current_cart_id); //storing the information in session. session()->put('cart_data', [$current_cart, $cart_products]); session()->flash('Success', 'Item Added To Cart Successfully'); - dump($cart_products); - - //return the control to the controller + //return the control to the controller. return redirect()->back(); } else { - //repair the cart, will remake the session + //repair the cart, will remake the session. //and add the product in the new cart instance. $this->repairCart($cart_session_id, $id); } } else { //function call - $this->createNewCart($id); + $this->createNewCart($id, $data); } } @@ -128,11 +133,12 @@ class Cart { * @return mixed */ - public function createNewCart($id) { + public function createNewCart($id, $data) { $fresh_cart_session_id = session()->getId(); - $data['session_id'] = $fresh_cart_session_id; + if(!auth()->guard('customer')->check()) + $data['session_id'] = $fresh_cart_session_id; $data['channel_id'] = core()->getCurrentChannel()->id; @@ -144,11 +150,13 @@ class Cart { $cart_product['product_id'] = $id; - $cart_product['quantity'] = 1; + $cart_product['quantity'] = $data['quantity']; $cart_product['cart_id'] = $new_cart_id; - if($cart_product = $this->cart->attach($new_cart_id, $cart_product['product_id'], $cart_product['quantity'])) { + $cart_product['price'] = $data['price']; + + if($cart_product = $this->cart->attach($new_cart_id, $cart_product['product_id'], $cart_product['quantity'], $cart_product['price'])) { session()->put('cart_data', [$cart, $cart_product]); @@ -248,7 +256,7 @@ class Cart { of the logged in user. */ - public function add($id) { + public function add($id, $itemdata) { $products = array(); @@ -272,24 +280,32 @@ class Cart { * table. */ if(isset($customer_cart)) { - $customer_cart_products = $this->cart->getProducts($customer_cart_id); + $customer_cart_items = $this->cart->items($customer_cart_id); + + $customer_cart_products = array(); + + foreach($customer_cart_items as $customer_cart_item) { + array_push($customer_cart_products, $this->cartItem->getProduct($customer_cart_item->id)); + } if (isset($customer_cart_products)) { foreach ($customer_cart_products as $customer_cart_product) { - if($customer_cart_product->id == $id) { - dump('Item already exists in cart'); + if($customer_cart_product == $id) { + $cartItemId = $this->cartItem->findOneByField('product_id', $id)->id; + + $cartItemQuantity = $this->cartItem->findOneByField('product_id', $id)->quantity; + + $this->cartItem->update(['quantity' => $cartItemQuantity + $itemdata['quantity']], $cartItemId); session()->flash('error', 'Item already exists in cart'); return redirect()->back(); - - //maybe increase the quantity in here } } //add the product in the cart - $this->cart->attach($customer_cart_id, $id, 1); + $this->cart->attach($customer_cart_id, $id, $itemdata['quantity'], $itemdata['price']); session()->flash('success', 'Item Added To Cart Successfully'); @@ -315,7 +331,7 @@ class Cart { if($new_cart = $this->cart->create($data)) { $new_cart_id = $new_cart->id ?? $new_cart['id']; - $this->cart->attach($new_cart_id, $id, 1); + $this->cart->attach($new_cart_id, $id, $itemdata['quantity'], $itemdata['price']); session()->flash('success', 'Item Added To Cart Successfully'); @@ -370,46 +386,60 @@ class Cart { $guest_cart = $this->cart->findOneByField('session_id', $cart_session_id); if(!isset($guest_cart)) { - dd('Some One Deleted Cart or it wasn\'t there from the start'); + dd('Some One Deleted Cart'); return redirect()->back(); } + $guest_cart_items = $this->cart->items($guest_cart->id); - $guest_cart_products = $this->cart->getProducts($guest_cart->id); + $guest_cart_products = array(); + + foreach($guest_cart_items as $guest_cart_item) { + array_push($guest_cart_products, $this->cartItem->getProduct($guest_cart_item->id)); + } //check if the current logged in customer is also //having any previously saved cart instances. $customer_cart = $this->cart->findOneByField('customer_id', $customer_id); if(isset($customer_cart)) { - $customer_cart_products = $this->cart->getProducts($customer_cart->id); + $customer_cart_items = $this->cart->items($customer_cart->id); + + $customer_cart_products = array(); + + foreach($customer_cart_items as $customer_cart_item) { + array_push($customer_cart_products, $this->cartItem->getProduct($customer_cart_item->id)); + } foreach($guest_cart_products as $key => $guest_cart_product) { - foreach($customer_cart_products as $customer_cart_product) { + if($guest_cart_product == $customer_cart_product) { + $cartItemId = $this->cartItem->findWhere(['cart_id'=> $guest_cart->id, 'product_id' => $guest_cart_product])[0]->id; - if($guest_cart_product->id == $customer_cart_product->id) { + $cartItemQuantity = $this->cartItem->findWhere(['cart_id'=> $guest_cart->id, 'product_id' => $guest_cart_product])[0]->quantity; - $quantity = $guest_cart_product->toArray()['pivot']['quantity'] + 1; + $customerItemId = $this->cartItem->findWhere(['cart_id'=> $customer_cart->id, 'product_id' => $customer_cart_product])[0]->id; - $pivot = $guest_cart_product->toArray()['pivot']; + $customerItemQuantity = $this->cartItem->findWhere(['cart_id'=> $customer_cart->id, 'product_id' => $customer_cart_product])[0]->quantity; - $saveQuantity = $this->cart->updateRelatedForMerge($pivot, 'quantity', $quantity); + $this->cartItem->delete($cartItemId); + + $this->cartItem->update(['quantity' => $cartItemQuantity + $customerItemQuantity], $customerItemId); unset($guest_cart_products[$key]); } } } - //insert the new products here. foreach ($guest_cart_products as $key => $guest_cart_product) { - $product = $guest_cart_product->toArray(); + // dd($this->cartItem->findWhere(['cart_id'=> $guest_cart->id, 'product_id' => $guest_cart_product])[0]); + $cartItemId = $this->cartItem->findWhere(['cart_id'=> $guest_cart->id, 'product_id' => $guest_cart_product])[0]->id; - $this->cart->updateRelatedForMerge($product['pivot'], 'cart_id', $customer_cart->id); + $this->cartItem->update(['cart_id' => $customer_cart->id], $cartItemId); } //detach with guest cart records - $this->cart->detachAndDeleteParent($guest_cart->id); + $this->cart->deleteParent($guest_cart->id); Cookie::queue(Cookie::forget('cart_session_id')); diff --git a/packages/Webkul/Cart/src/Database/migrations/2018_09_05_150444_create_cart_table.php b/packages/Webkul/Cart/src/Database/Migrations/2018_09_05_150444_create_cart_table.php similarity index 100% rename from packages/Webkul/Cart/src/Database/migrations/2018_09_05_150444_create_cart_table.php rename to packages/Webkul/Cart/src/Database/Migrations/2018_09_05_150444_create_cart_table.php diff --git a/packages/Webkul/Cart/src/Database/migrations/2018_09_05_150915_create_cart_products_table.php b/packages/Webkul/Cart/src/Database/Migrations/2018_09_05_150915_create_cart_items_table.php similarity index 93% rename from packages/Webkul/Cart/src/Database/migrations/2018_09_05_150915_create_cart_products_table.php rename to packages/Webkul/Cart/src/Database/Migrations/2018_09_05_150915_create_cart_items_table.php index 5d3f4b2ce..0ab6260f7 100644 --- a/packages/Webkul/Cart/src/Database/migrations/2018_09_05_150915_create_cart_products_table.php +++ b/packages/Webkul/Cart/src/Database/Migrations/2018_09_05_150915_create_cart_items_table.php @@ -13,7 +13,7 @@ class CreateCartProductsTable extends Migration */ public function up() { - Schema::create('cart_products', function (Blueprint $table) { + Schema::create('cart_items', function (Blueprint $table) { $table->increments('id'); $table->integer('product_id')->unsigned(); $table->foreign('product_id')->references('id')->on('products'); diff --git a/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_092845_create_cart_address.php b/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_092845_create_cart_address.php new file mode 100644 index 000000000..070ea4609 --- /dev/null +++ b/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_092845_create_cart_address.php @@ -0,0 +1,43 @@ +increments('id'); + $table->string('address1'); + $table->string('address2')->nullable(); + $table->string('country'); + $table->string('state'); + $table->string('city'); + $table->integer('postcode'); + $table->string('phone'); + $table->string('address_type'); + $table->integer('cart_id')->nullable()->unsigned(); + $table->foreign('cart_id')->references('id')->on('cart'); + $table->integer('customer_id')->nullable()->unsigned(); + $table->foreign('customer_id')->references('id')->on('customers'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('cart_address'); + } +} diff --git a/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_093453_create_cart_payment.php b/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_093453_create_cart_payment.php new file mode 100644 index 000000000..9521ad2b6 --- /dev/null +++ b/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_093453_create_cart_payment.php @@ -0,0 +1,34 @@ +increments('id'); + $table->string('method'); + $table->integer('cart_id')->nullable()->unsigned(); + $table->foreign('cart_id')->references('id')->on('cart'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('cart_payment'); + } +} diff --git a/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_093508_create_cart_shipping.php b/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_093508_create_cart_shipping.php new file mode 100644 index 000000000..9413012ae --- /dev/null +++ b/packages/Webkul/Cart/src/Database/Migrations/2018_09_19_093508_create_cart_shipping.php @@ -0,0 +1,41 @@ +increments('id'); + $table->string('carrier'); + $table->string('carrier_title'); + $table->string('method'); + $table->string('method_title'); + $table->string('method_description')->nullable(); + $table->double('price')->nullable(); + $table->integer('cart_id')->nullable()->unsigned(); + $table->foreign('cart_id')->references('id')->on('cart'); + $table->integer('cart_address_id')->nullable()->unsigned(); + $table->foreign('cart_address_id')->references('id')->on('cart_address'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('cart_shipping'); + } +} diff --git a/packages/Webkul/Cart/src/Http/Controllers/CartController.php b/packages/Webkul/Cart/src/Http/Controllers/CartController.php index 101d28b9a..4dce35386 100644 --- a/packages/Webkul/Cart/src/Http/Controllers/CartController.php +++ b/packages/Webkul/Cart/src/Http/Controllers/CartController.php @@ -7,7 +7,10 @@ use Illuminate\Http\Response; //Cart repositories use Webkul\Cart\Repositories\CartRepository; -use Webkul\Cart\Repositories\CartProductRepository; +use Webkul\Cart\Repositories\CartItemRepository; + +//Product Repository +use Webkul\Product\Repositories\ProductRepository; //Customer repositories use Webkul\Customer\Repositories\CustomerRepository; @@ -36,11 +39,13 @@ class CartController extends Controller protected $cart; - protected $cartProduct; + protected $cartItem; protected $customer; - public function __construct(CartRepository $cart, CartProductRepository $cartProduct, CustomerRepository $customer) { + protected $product; + + public function __construct(CartRepository $cart, CartItemRepository $cartItem, CustomerRepository $customer, ProductRepository $product) { $this->middleware('customer')->except(['add', 'remove', 'test']); @@ -48,7 +53,9 @@ class CartController extends Controller $this->cart = $cart; - $this->cartProduct = $cartProduct; + $this->cartItem = $cartItem; + + $this->product = $product; } /** @@ -60,11 +67,26 @@ class CartController extends Controller */ public function add($id) { + $data = request()->input(); + // dd($data); + if(!isset($data['is_configurable']) || !isset($data['product']) ||!isset($data['quantity'])) { + session()->flash('error', 'Cannot Product Due to User\'s miscreancy in system\'s integrity'); + + return redirect()->back(); + } + + if($data['is_configurable'] == "false") { + $data['price'] = $this->product->findOneByField('id', $data['product'])->price; + } else { + $id = $data['selected_configurable_option']; + + $data['price'] = $this->product->findOneByField('id', $data['selected_configurable_option'])->price; + } if(auth()->guard('customer')->check()) { - Cart::add($id); + Cart::add($id, $data); } else { - Cart::guestUnitAdd($id); + Cart::guestUnitAdd($id, $data); } return redirect()->back(); @@ -81,20 +103,26 @@ class CartController extends Controller return redirect()->back(); } - // public function test() { - // $cookie = Cookie::get('cart_session_id'); + /** + * This is a test for + * relationship existence + * from cart item to product + * + * @return Array + */ + public function test() { + $cartItems = $this->cart->items(75); - // $cart = $this->cart->findOneByField('session_id', $cookie); + $products = array(); + foreach($cartItems as $cartItem) { + $cartItemId = $cartItem->id; - // $cart_products = $this->cart->getProducts($cart->id); + $this->cart->updateItem(75, $cartItemId, 'quantity', $cartItem->quantity+1); - // foreach($cart_products as $cart_product) { - // $quantity = $cart_product->toArray()['pivot']['quantity'] + 1; + array_push($products, ['product_id' => $this->cartItem->getProduct($cartItemId), 'quantity' => $cartItem->quantity]); + } - // $pivot = $cart_product->toArray()['pivot']; - - // $saveQuantity = $this->cart->saveRelated($pivot, 'quantity', $quantity+1); - // } - // dd('done'); - // } + dd($products); + return response()->json($products, 200); + } } \ No newline at end of file diff --git a/packages/Webkul/Cart/src/Http/Controllers/CheckoutController.php b/packages/Webkul/Cart/src/Http/Controllers/CheckoutController.php index b763fc1e9..058b8ac5b 100644 --- a/packages/Webkul/Cart/src/Http/Controllers/CheckoutController.php +++ b/packages/Webkul/Cart/src/Http/Controllers/CheckoutController.php @@ -5,6 +5,7 @@ use Illuminate\Routing\Controller; use Illuminate\Http\Request; use Illuminate\Http\Response; use Auth; +use Webkul\Shipping\Facades\Shipping; /** * Chekout controller for the customer @@ -15,7 +16,6 @@ use Auth; */ class CheckoutController extends Controller { - /** * Contains route related configuration * @@ -43,4 +43,34 @@ class CheckoutController extends Controller return view($this->_config['view']); } + /** + * Saves customer address. + * + * @return \Illuminate\Http\Response + */ + public function saveAddress() + { + + return response()->json([ + 'shipping' => Shipping::collectRates() + ]); + } + + /** + * Saves shipping method. + * + * @return \Illuminate\Http\Response + */ + public function saveShipping() + { + } + + /** + * Saves payment method. + * + * @return \Illuminate\Http\Response + */ + public function saveAPayment() + { + } } \ No newline at end of file diff --git a/packages/Webkul/Cart/src/Http/ViewComposers/CartComposer.php b/packages/Webkul/Cart/src/Http/ViewComposers/CartComposer.php index a216c1d5c..210e95017 100644 --- a/packages/Webkul/Cart/src/Http/ViewComposers/CartComposer.php +++ b/packages/Webkul/Cart/src/Http/ViewComposers/CartComposer.php @@ -7,6 +7,9 @@ use Illuminate\Support\Collection; use Webkul\Cart\Repositories\CartRepository; +use Webkul\Cart\Repositories\CartItemRepository; + + use Cookie; use Cart; /** @@ -32,27 +35,42 @@ class CartComposer * @param View $view * @return void */ - public function __construct(CartRepository $cart) { + public function __construct(CartRepository $cart, CartItemRepository $cartItem) { $this->cart = $cart; + + $this->cartItem = $cartItem; } public function compose(View $view) { if(auth()->guard('customer')->check()) { $cart = $this->cart->findOneByField('customer_id', auth()->guard('customer')->user()->id); - $cart_products = $this->cart->getProducts($cart['id']); + if(isset($cart)) { + $cart_items = $this->cart->items($cart['id']); - // dd($cart_products); + $cart_products = array(); - $view->with('cart', $cart_products); + foreach($cart_items as $cart_item) { + array_push($cart_products, $this->cartItem->getProduct($cart_item->id)); + } + $view->with('cart', $cart_products); + } } else { if(Cookie::has('cart_session_id')) { $cart = $this->cart->findOneByField('session_id', Cookie::get('cart_session_id')); - $cart_products = $this->cart->getProducts($cart['id']); + if(isset($cart)) { + $cart_items = $this->cart->items($cart['id']); - $view->with('cart', $cart_products); + $cart_products = array(); + + foreach($cart_items as $cart_item) { + array_push($cart_products, $this->cartItem->getProduct($cart_item->id)); + } + + $view->with('cart', $cart_products); + } } } } diff --git a/packages/Webkul/Cart/src/Models/Cart.php b/packages/Webkul/Cart/src/Models/Cart.php index f1591cdb4..519507600 100644 --- a/packages/Webkul/Cart/src/Models/Cart.php +++ b/packages/Webkul/Cart/src/Models/Cart.php @@ -3,8 +3,9 @@ namespace Webkul\Cart\Models; use Illuminate\Database\Eloquent\Model; - use Webkul\Product\Models\Product; +use Webkul\Cart\Models\CartAddress; +use Webkul\Cart\Models\CartShipping; class Cart extends Model { @@ -16,6 +17,26 @@ class Cart extends Model public function with_products() { - return $this->belongsToMany(Product::class, 'cart_products')->withPivot('id', 'product_id','quantity', 'cart_id'); + return $this->belongsToMany(Product::class, 'cart_items')->withPivot('id', 'product_id','quantity', 'cart_id'); + } + + public function items() { + return $this->hasMany('Webkul\Cart\Models\CartItem'); + } + + /** + * Get the addresses for the cart. + */ + public function addresses() + { + return $this->hasMany(CartAddress::class); + } + + /** + * Get the shipping for the cart. + */ + public function shipping() + { + return $this->hasMany(CartShipping::class); } } diff --git a/packages/Webkul/Cart/src/Models/CartAddress.php b/packages/Webkul/Cart/src/Models/CartAddress.php new file mode 100644 index 000000000..5ecad6830 --- /dev/null +++ b/packages/Webkul/Cart/src/Models/CartAddress.php @@ -0,0 +1,10 @@ +hasOne('Webkul\Product\Models\Product', 'id', 'product_id'); + } +} diff --git a/packages/Webkul/Cart/src/Models/CartProduct.php b/packages/Webkul/Cart/src/Models/CartProduct.php deleted file mode 100644 index 8b8a9d32b..000000000 --- a/packages/Webkul/Cart/src/Models/CartProduct.php +++ /dev/null @@ -1,11 +0,0 @@ -alias('cart', CartFacade::class); + + $loader->alias('cart', Cart::class); $this->app->singleton('cart', function () { - return new Cart(); + return new cart(); }); + + $this->app->bind('cart', 'Webkul\Cart\Cart'); } -} +} \ No newline at end of file diff --git a/packages/Webkul/Cart/src/Repositories/CartProductRepository.php b/packages/Webkul/Cart/src/Repositories/CartItemRepository.php similarity index 80% rename from packages/Webkul/Cart/src/Repositories/CartProductRepository.php rename to packages/Webkul/Cart/src/Repositories/CartItemRepository.php index 0c3636d5d..78f2e615d 100644 --- a/packages/Webkul/Cart/src/Repositories/CartProductRepository.php +++ b/packages/Webkul/Cart/src/Repositories/CartItemRepository.php @@ -11,7 +11,7 @@ use Webkul\Core\Eloquent\Repository; * @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com) */ -class CartProductRepository extends Repository +class CartItemRepository extends Repository { /** * Specify Model class name @@ -21,7 +21,7 @@ class CartProductRepository extends Repository function model() { - return 'Webkul\Cart\Models\CartProduct'; + return 'Webkul\Cart\Models\CartItem'; } /** @@ -51,4 +51,8 @@ class CartProductRepository extends Repository return $cartitems; } + + public function getProduct($cartItemId) { + return $this->model->find($cartItemId)->product->id; + } } \ No newline at end of file diff --git a/packages/Webkul/Cart/src/Repositories/CartRepository.php b/packages/Webkul/Cart/src/Repositories/CartRepository.php index e7f951abd..2ba0cde9f 100644 --- a/packages/Webkul/Cart/src/Repositories/CartRepository.php +++ b/packages/Webkul/Cart/src/Repositories/CartRepository.php @@ -63,9 +63,8 @@ class CartRepository extends Repository * * @return Mixed */ - public function attach($cart_id, $product_id, $quantity) { - - return $this->model->findOrFail($cart_id)->with_products()->attach($cart_id, ['product_id' => $product_id, 'cart_id' => $cart_id, 'quantity' => $quantity]); + public function attach($cart_id, $product_id, $quantity, $price) { + return $this->model->findOrFail($cart_id)->with_products()->attach($cart_id, ['product_id' => $product_id, 'cart_id' => $cart_id, 'quantity' => $quantity, 'price' => $price]); } @@ -77,12 +76,25 @@ class CartRepository extends Repository * * @return Mixed */ - public function updateRelatedForMerge($pivot, $column, $value) { - $cart_product = $this->model->findOrFail($pivot['cart_id']); + public function updateRelatedForMerge($cart_id, $product_id, $column, $value) { + $cart_product = $this->model->findOrFail($cart_id); - return $cart_product->with_products()->updateExistingPivot($pivot['product_id'], array($column => $value)); + return $cart_product->with_products()->updateExistingPivot($product_id, array($column => $value)); } + /** + * Update the quantity of + * previously added item + * in the cart. + * + * @return Mixed + */ + + // public function updateRelatedInItems($cartId, $cartItemId, $column, $value) { + + // return $this->updateItem($cartId)->syncWithoutDetaching($cartItemId, [$column => $value]); + // } + /** * Method to detach * associations. @@ -92,12 +104,13 @@ class CartRepository extends Repository * * @return Mixed */ - public function detachAndDeleteParent($cart_id) { + public function deleteParent($cart_id) { $cart = $this->model->find($cart_id); - //apply strict check for verifying guest ownership on this record. - $cart->with_products()->detach(); - return $this->model->destroy($cart_id); } + + public function items($cartId) { + return $this->model->find($cartId)->items; + } } \ No newline at end of file diff --git a/packages/Webkul/Core/src/Database/Migrations/2018_09_20_060658_create_core_config_table.php b/packages/Webkul/Core/src/Database/Migrations/2018_09_20_060658_create_core_config_table.php new file mode 100644 index 000000000..3f287656d --- /dev/null +++ b/packages/Webkul/Core/src/Database/Migrations/2018_09_20_060658_create_core_config_table.php @@ -0,0 +1,34 @@ +increments('id'); + $table->string('code'); + $table->string('value'); + $table->integer('channel_id')->unsigned(); + $table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('core_config'); + } +} diff --git a/packages/Webkul/Core/src/Providers/CoreServiceProvider.php b/packages/Webkul/Core/src/Providers/CoreServiceProvider.php index 2c036ddca..f0d7e4113 100644 --- a/packages/Webkul/Core/src/Providers/CoreServiceProvider.php +++ b/packages/Webkul/Core/src/Providers/CoreServiceProvider.php @@ -33,6 +33,7 @@ class CoreServiceProvider extends ServiceProvider Validator::extend('slug', 'Webkul\Core\Contracts\Validations\Slug@passes'); Validator::extend('code', 'Webkul\Core\Contracts\Validations\Code@passes'); } + /** * Register services. * diff --git a/packages/Webkul/Customer/src/Http/Controllers/CustomerController.php b/packages/Webkul/Customer/src/Http/Controllers/CustomerController.php index a8501b133..913ecdd9d 100644 --- a/packages/Webkul/Customer/src/Http/Controllers/CustomerController.php +++ b/packages/Webkul/Customer/src/Http/Controllers/CustomerController.php @@ -5,6 +5,7 @@ namespace Webkul\Customer\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\Response; use Webkul\Customer\Repositories\CustomerRepository; +use Webkul\Product\Repositories\ProductReviewRepository as ProductReview; use Webkul\Customer\Models\Customer; use Auth; @@ -27,14 +28,29 @@ class CustomerController extends Controller protected $_config; protected $customer; + /** + * ProductReviewRepository object + * + * @var array + */ + protected $productReview; - public function __construct(CustomerRepository $customer) + /** + * Create a new controller instance. + * + * @param Webkul\Product\Repositories\ProductReviewRepository $productReview + * @return void + */ + + public function __construct(CustomerRepository $customer , ProductReview $productReview) { $this->middleware('customer'); $this->_config = request('_config'); $this->customer = $customer; + + $this->productReview = $productReview; } /** @@ -141,7 +157,12 @@ class CustomerController extends Controller } public function reviews() { - return view($this->_config['view']); + + $id = auth()->guard('customer')->user()->id; + + $reviews = $this->productReview->getCustomerReview($id); + + return view($this->_config['view'],compact('reviews')); } public function address() { diff --git a/packages/Webkul/Payment/Payment.php b/packages/Webkul/Payment/Payment.php new file mode 100644 index 000000000..543172f86 --- /dev/null +++ b/packages/Webkul/Payment/Payment.php @@ -0,0 +1,32 @@ + $object->getCode(), + 'title' => $object->getTitle(), + 'description' => $object->getDescription(), + ]; + } + } + + return $paymentMethods; + } +} \ No newline at end of file diff --git a/packages/Webkul/Payment/composer.json b/packages/Webkul/Payment/composer.json new file mode 100644 index 000000000..7806912d2 --- /dev/null +++ b/packages/Webkul/Payment/composer.json @@ -0,0 +1,27 @@ +{ + "name": "webkul/laravel-payment", + "license": "MIT", + "authors": [ + { + "name": "Jitendra Singh", + "email": "jitendra@webkul.com" + } + ], + "require": {}, + "autoload": { + "psr-4": { + "Webkul\\Payment\\": "src/" + } + }, + "extra": { + "laravel": { + "providers": [ + "Webkul\\Payment\\Providers\\PaymentServiceProvider" + ], + "aliases": { + "Bouncer": "Webkul\\Payment\\Facades\\Bouncer" + } + } + }, + "minimum-stability": "dev" +} diff --git a/packages/Webkul/Payment/src/Facades/Payment.php b/packages/Webkul/Payment/src/Facades/Payment.php new file mode 100644 index 000000000..ee919d03b --- /dev/null +++ b/packages/Webkul/Payment/src/Facades/Payment.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/packages/Webkul/Payment/src/Payment/CashOnDelivery.php b/packages/Webkul/Payment/src/Payment/CashOnDelivery.php new file mode 100644 index 000000000..8db87b36f --- /dev/null +++ b/packages/Webkul/Payment/src/Payment/CashOnDelivery.php @@ -0,0 +1,13 @@ +getConfigData('active'); + } + + /** + * Returns payment method code + * + * @return array + */ + public function getCode() + { + if (empty($this->code)) { + // throw exception + } + + return $this->_code; + } + + /** + * Returns payment method title + * + * @return array + */ + public function getTitle() + { + return $this->getConfigData('title'); + } + + /** + * Returns payment method decription + * + * @return array + */ + public function getDecription() + { + return $this->getConfigData('decription'); + } + + /** + * Retrieve information from payment configuration + * + * @param string $field + * @param int|string|null $channelId + * + * @return mixed + */ + public function getConfigData($field, $channelId = null) + { + if (null === $channelId) { + $channelId = core()->getCurrentChannel()->getId(); + } + + $paymentConfig = Config::get('paymentmethods' . $this->getCode()); + + return $paymentConfig[$field]; + } +} \ No newline at end of file diff --git a/packages/Webkul/Payment/src/Providers/PaymentServiceProvider.php b/packages/Webkul/Payment/src/Providers/PaymentServiceProvider.php new file mode 100644 index 000000000..2bd28d181 --- /dev/null +++ b/packages/Webkul/Payment/src/Providers/PaymentServiceProvider.php @@ -0,0 +1,46 @@ +registerFacades(); + } + /** + * Register Bouncer as a singleton. + * + * @return void + */ + protected function registerFacades() + { + $loader = AliasLoader::getInstance(); + $loader->alias('payment', PaymentFacade::class); + + $this->app->singleton('payment', function () { + return new Payment(); + }); + } +} diff --git a/packages/Webkul/Product/src/Contracts/Criteria/AttributeToSelectCriteria.php b/packages/Webkul/Product/src/Contracts/Criteria/AttributeToSelectCriteria.php index cc86260e7..4f5a47cff 100644 --- a/packages/Webkul/Product/src/Contracts/Criteria/AttributeToSelectCriteria.php +++ b/packages/Webkul/Product/src/Contracts/Criteria/AttributeToSelectCriteria.php @@ -59,13 +59,13 @@ class AttributeToSelectCriteria extends AbstractProduct implements CriteriaInter public function apply($model, RepositoryInterface $repository) { $model = $model->select('products.*'); - + foreach ($this->attributeToSelect as $code) { $attribute = $this->attribute->findOneByField('code', $code); if(!$attribute) continue; - + $productValueAlias = 'pav_' . $attribute->code; $model = $model->leftJoin('product_attribute_values as ' . $productValueAlias, function($qb) use($attribute, $productValueAlias) { diff --git a/packages/Webkul/Core/src/Http/Controllers/ReviewController.php b/packages/Webkul/Product/src/Http/Controllers/ReviewController.php similarity index 61% rename from packages/Webkul/Core/src/Http/Controllers/ReviewController.php rename to packages/Webkul/Product/src/Http/Controllers/ReviewController.php index ac6b76995..3428b1f2b 100644 --- a/packages/Webkul/Core/src/Http/Controllers/ReviewController.php +++ b/packages/Webkul/Product/src/Http/Controllers/ReviewController.php @@ -1,6 +1,6 @@ _config = request('_config'); } - /** - * Store a newly created resource in storage. + /** + * Display a listing of the resource. * - * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function index() + { + return view($this->_config['view']); + } + + /** + * Show the form for editing the specified resource. + * + * @param int $id * @return \Illuminate\Http\Response */ - public function store(Request $request , $id) - { - $this->validate(request(), [ - 'comment' => 'required', - ]); + public function edit($id) + { + $review = $this->productReview->find($id); - $input=$request->all(); + return view($this->_config['view'],compact('review')); + } - $input['product_id']=$id; + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { - $input['customer_id']=1; + $this->productReview->update(request()->all(), $id); - $this->productReview->create($input); - - session()->flash('success', 'Review submitted successfully.'); + session()->flash('success', 'Review updated successfully.'); return redirect()->route($this->_config['redirect']); } - } diff --git a/packages/Webkul/Product/src/Models/Product.php b/packages/Webkul/Product/src/Models/Product.php index 1ca1cf59c..73c475242 100644 --- a/packages/Webkul/Product/src/Models/Product.php +++ b/packages/Webkul/Product/src/Models/Product.php @@ -157,7 +157,7 @@ class Product extends Model * @return mixed */ public function getAttribute($key) - { + { if (!method_exists(self::class, $key) && !in_array($key, ['parent_id', 'attribute_family_id']) && !isset($this->attributes[$key])) { if (isset($this->id) && $this->isCustomAttribute($key)) { $this->attributes[$key] = ''; diff --git a/packages/Webkul/Product/src/Models/ProductReview.php b/packages/Webkul/Product/src/Models/ProductReview.php index a6ed903ec..cad0146d5 100644 --- a/packages/Webkul/Product/src/Models/ProductReview.php +++ b/packages/Webkul/Product/src/Models/ProductReview.php @@ -4,6 +4,7 @@ namespace Webkul\Product\Models; use Illuminate\Database\Eloquent\Model; use Webkul\Customer\Models\Customer; +use Webkul\Product\Models\Product; class ProductReview extends Model { @@ -16,4 +17,12 @@ class ProductReview extends Model { return $this->belongsTo(Customer::class); } + + /** + * Get the product. + */ + public function product() + { + return $this->belongsTo(Product::class); + } } \ No newline at end of file diff --git a/packages/Webkul/Product/src/Product/Review.php b/packages/Webkul/Product/src/Product/Review.php index 3fc979da2..72a4d910b 100644 --- a/packages/Webkul/Product/src/Product/Review.php +++ b/packages/Webkul/Product/src/Product/Review.php @@ -56,7 +56,7 @@ class Review extends AbstractProduct */ public function getTotalRating($product) { - return $product->reviews()->where('status',1)->sum('rating'); + return $product->reviews()->where('status','approved')->sum('rating'); } /** @@ -101,7 +101,7 @@ class Review extends AbstractProduct $link = $_SERVER['PHP_SELF']; $link_array = explode('/',$link); $last=end($link_array); - $itemPerPage = $last*5; + $itemPerPage = 1*5; return $product->reviews()->where('status',1)->paginate($itemPerPage); } } \ No newline at end of file diff --git a/packages/Webkul/Product/src/Repositories/ProductReviewRepository.php b/packages/Webkul/Product/src/Repositories/ProductReviewRepository.php index e8bff8b5e..4e135b324 100644 --- a/packages/Webkul/Product/src/Repositories/ProductReviewRepository.php +++ b/packages/Webkul/Product/src/Repositories/ProductReviewRepository.php @@ -1,8 +1,10 @@ -product = $product; + + parent::__construct($app); + } + /** * Specify Model class name * @@ -21,4 +45,16 @@ class ProductReviewRepository extends Repository { return 'Webkul\Product\Models\ProductReview'; } + + /** + * Retrieve review for customerId + * + * @param int $customerId + */ + function getCustomerReview($customerId) + { + $reviews = $this->model->where('customer_id',$customerId)->with('product')->get(); + + return $reviews; + } } \ No newline at end of file diff --git a/packages/Webkul/Shipping/src/Carriers/AbstractShipping.php b/packages/Webkul/Shipping/src/Carriers/AbstractShipping.php new file mode 100644 index 000000000..55cb97848 --- /dev/null +++ b/packages/Webkul/Shipping/src/Carriers/AbstractShipping.php @@ -0,0 +1,82 @@ + + * @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com) + */ +abstract class AbstractShipping +{ + + abstract public function calculate(); + + /** + * Checks if payment method is available + * + * @return array + */ + public function isAvailable() + { + return $this->getConfigData('active'); + } + + /** + * Returns payment method code + * + * @return array + */ + public function getCode() + { + if (empty($this->code)) { + // throw exception + } + + return $this->code; + } + + /** + * Returns payment method title + * + * @return array + */ + public function getTitle() + { + return $this->getConfigData('title'); + } + + /** + * Returns payment method decription + * + * @return array + */ + public function getDecription() + { + return $this->getConfigData('decription'); + } + + /** + * Retrieve information from payment configuration + * + * @param string $field + * @param int|string|null $channelId + * + * @return mixed + */ + public function getConfigData($field, $channelId = null) + { + if (null === $channelId) { + $channelId = core()->getCurrentChannel()->id; + } + + $shippingConfig = Config::get('carriers.' . $this->getCode()); + + return $shippingConfig[$field]; + } + +} +?> \ No newline at end of file diff --git a/packages/Webkul/Shipping/src/Carriers/FlatRate.php b/packages/Webkul/Shipping/src/Carriers/FlatRate.php index ba3faa6c7..ec9a1457c 100644 --- a/packages/Webkul/Shipping/src/Carriers/FlatRate.php +++ b/packages/Webkul/Shipping/src/Carriers/FlatRate.php @@ -2,8 +2,8 @@ namespace Webkul\Shipping\Carriers; -use Webkul\Shipping\Contracts\AbstractShipping; use Config; +use Webkul\Cart\Models\CartShipping; /** * Class Rate. @@ -11,8 +11,40 @@ use Config; */ class FlatRate extends AbstractShipping { + /** + * Payment method code + * + * @var string + */ + protected $code = 'flatrate'; + public function calculate() { - return []; + return [ + 'carrier_code' => 'flatrate', + 'carrier_title' => 'Flat Rate', + 'carrier_description' => '', + 'rates' => [ + [ + 'method' => 'flatrate_flatrate', + 'method_title' => 'Flat Rate', + 'price' => 10, + 'price_formated' => core()->currency(10), + ] + ] + ]; + + $object = new CartShipping; + + $object->carrier = 'flatrate_flatrate'; + $object->carrier_title = $this->getConfigData('description'); + $object->method = 'flatrate'; + $object->method_title = $this->getConfigData('title'); + $object->method_description = $this->getConfigData('description'); + $object->price = 10; + + return [ + 'flatrate' => [$object] + ]; } } \ No newline at end of file diff --git a/packages/Webkul/Shipping/src/Contracts/AbstractShipping.php b/packages/Webkul/Shipping/src/Contracts/AbstractShipping.php deleted file mode 100644 index bce60f009..000000000 --- a/packages/Webkul/Shipping/src/Contracts/AbstractShipping.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -abstract class AbstractShipping -{ - - abstract public function calculate(); - -} -?> \ No newline at end of file diff --git a/packages/Webkul/Shipping/src/Facades/Shipping.php b/packages/Webkul/Shipping/src/Facades/Shipping.php new file mode 100644 index 000000000..65ba5ad85 --- /dev/null +++ b/packages/Webkul/Shipping/src/Facades/Shipping.php @@ -0,0 +1,18 @@ +calculate()) { - $rates[] = $rate; - } - } - - return $rates; - } -} \ No newline at end of file diff --git a/packages/Webkul/Shipping/src/Http/helpers.php b/packages/Webkul/Shipping/src/Http/helpers.php new file mode 100644 index 000000000..93a8f1baa --- /dev/null +++ b/packages/Webkul/Shipping/src/Http/helpers.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/packages/Webkul/Shipping/src/Providers/ShippingServiceProvider.php b/packages/Webkul/Shipping/src/Providers/ShippingServiceProvider.php index 4757cce0d..f7a29055d 100644 --- a/packages/Webkul/Shipping/src/Providers/ShippingServiceProvider.php +++ b/packages/Webkul/Shipping/src/Providers/ShippingServiceProvider.php @@ -3,8 +3,11 @@ namespace Webkul\Shipping\Providers; use Illuminate\Support\ServiceProvider; +use Illuminate\Foundation\AliasLoader; use Illuminate\Routing\Router; use Webkul\Customer\Http\Middleware\RedirectIfNotCustomer; +use Webkul\Shipping\Shipping; +use Webkul\Shipping\Facades\Shipping as ShippingFacade; class ShippingServiceProvider extends ServiceProvider { @@ -15,8 +18,9 @@ class ShippingServiceProvider extends ServiceProvider */ public function boot(Router $router) { + include __DIR__ . '/../Http/helpers.php'; } - + /** * Register services. * @@ -24,6 +28,20 @@ class ShippingServiceProvider extends ServiceProvider */ public function register() { + $this->registerFacades(); + } + /** + * Register Bouncer as a singleton. + * + * @return void + */ + protected function registerFacades() + { + $loader = AliasLoader::getInstance(); + $loader->alias('shipping', ShippingFacade::class); + $this->app->singleton('shipping', function () { + return new Shipping(); + }); } } diff --git a/packages/Webkul/Shipping/src/Shipping.php b/packages/Webkul/Shipping/src/Shipping.php new file mode 100644 index 000000000..384c8b6f0 --- /dev/null +++ b/packages/Webkul/Shipping/src/Shipping.php @@ -0,0 +1,29 @@ +isAvailable()) { + $rates[] = $object->calculate(); + } + } + + return $rates; + + // return view('shop::checkout.onepage.shipping', compact('rates')); + } +} \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Http/Controllers/ProductController.php b/packages/Webkul/Shop/src/Http/Controllers/ProductController.php index b94ba5ade..f410aeb03 100644 --- a/packages/Webkul/Shop/src/Http/Controllers/ProductController.php +++ b/packages/Webkul/Shop/src/Http/Controllers/ProductController.php @@ -52,6 +52,8 @@ class ProductController extends Controller { $product = $this->product->findBySlugOrFail($slug); - return view($this->_config['view'], compact('product')); + $customer = auth()->guard('customer')->user(); + + return view($this->_config['view'], compact('product','customer')); } } diff --git a/packages/Webkul/Shop/src/Http/Controllers/ReviewController.php b/packages/Webkul/Shop/src/Http/Controllers/ReviewController.php index f6f6fb26a..4447db8b0 100644 --- a/packages/Webkul/Shop/src/Http/Controllers/ReviewController.php +++ b/packages/Webkul/Shop/src/Http/Controllers/ReviewController.php @@ -94,7 +94,7 @@ class ReviewController extends Controller $customer_id = auth()->guard('customer')->user()->id; - $data['status']=0; + $data['status']='pending'; $data['product_id']=$id; $data['customer_id']=$customer_id; diff --git a/packages/Webkul/Shop/src/Http/routes.php b/packages/Webkul/Shop/src/Http/routes.php index 7d8361989..8acf7735e 100644 --- a/packages/Webkul/Shop/src/Http/routes.php +++ b/packages/Webkul/Shop/src/Http/routes.php @@ -14,6 +14,14 @@ Route::group(['middleware' => ['web']], function () { 'view' => 'shop::checkout.onepage' ])->name('shop.checkout'); + Route::get('test', 'Webkul\Cart\Http\Controllers\CartController@test'); + + Route::post('/checkout/save-address', 'Webkul\Cart\Http\Controllers\CheckoutController@saveAddress')->name('shop.checkout.save-address'); + + Route::post('/checkout/save-shipping', 'Webkul\Cart\Http\Controllers\CheckoutController@saveShipping')->name('shop.checkout.save-shipping'); + + Route::post('/checkout/save-payment', 'Webkul\Cart\Http\Controllers\CheckoutController@savePayment')->name('shop.checkout.save-payment'); + /* dummy routes ends here */ @@ -39,12 +47,12 @@ Route::group(['middleware' => ['web']], function () { ])->name('shop.reviews.create'); Route::post('/product/{slug}/review', 'Webkul\Shop\Http\Controllers\ReviewController@store')->defaults('_config', [ - 'redirect' => 'shop.reviews.index' + 'redirect' => 'customer.reviews.index' ])->name('shop.reviews.store'); - Route::post('/reviews/create/{slug}', 'Webkul\Shop\Http\Controllers\ReviewController@store')->defaults('_config', [ - 'redirect' => 'admin.reviews.index' - ])->name('admin.reviews.store'); + // Route::post('/reviews/create/{slug}', 'Webkul\Shop\Http\Controllers\ReviewController@store')->defaults('_config', [ + // 'redirect' => 'admin.reviews.index' + // ])->name('admin.reviews.store'); //customer routes starts here diff --git a/packages/Webkul/Shop/src/Resources/assets/js/components/cart-dropdown.vue b/packages/Webkul/Shop/src/Resources/assets/js/components/cart-dropdown.vue index 9b27c8634..570197b9d 100644 --- a/packages/Webkul/Shop/src/Resources/assets/js/components/cart-dropdown.vue +++ b/packages/Webkul/Shop/src/Resources/assets/js/components/cart-dropdown.vue @@ -75,6 +75,8 @@ export default { initializeDropdown: function() { this.totalitems = this.items.length; + this.cart_items = this.items; + console.log("The cart items here are = ",cart_items); } } } diff --git a/packages/Webkul/Shop/src/Resources/assets/sass/app.scss b/packages/Webkul/Shop/src/Resources/assets/sass/app.scss index 22a724cbe..57981ed7f 100644 --- a/packages/Webkul/Shop/src/Resources/assets/sass/app.scss +++ b/packages/Webkul/Shop/src/Resources/assets/sass/app.scss @@ -1070,7 +1070,6 @@ section.slider-block { .addtocart { white-space: nowrap; font-size: 12px; - border-radius: 0px; } } } @@ -1174,7 +1173,6 @@ section.slider-block { .addtocart { white-space: nowrap; font-size: 12px; - border-radius: 0px; } } } @@ -1651,13 +1649,11 @@ section.product-detail { .addtocart { width: 293px; background: black; - border-radius: 0px; } .buynow { width: 293px; float:right; - border-radius: 0px; } } } @@ -1995,12 +1991,10 @@ section.product-detail { .addtocart { width: 49%; background: #000000; - border-radius: 0px; } .buynow { width: 49%; - border-radius: 0px; } } } @@ -4221,5 +4215,58 @@ section.review { } } +// review page end here -// review page start here \ No newline at end of file + +// customer section css start here + +.cusomer-section { + margin-left: 50px; + width:100%; + + .customer-section-info { + display: flex; + flex-direction: row; + border-top: 1px solid #E8E8E8; + + .pro-img { + margin-top: 10px; + margin-bottom: 5px; + + img { + height: 125px; + width: 100px; + } + } + + .pro-discription { + margin-left: 20px; + width: 100%; + + .title { + font-size: 16px; + color: #0031F0; + margin-top: 15px; + } + + .rating { + margin-top: 10px; + + .icon { + height: 16px; + width: 16px; + } + } + + .discription { + margin-top: 15px; + } + } + } + + .customer-section-info:last-child { + border-bottom: 1px solid #e8e8e8; + } +} + +// customer section css end here \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Resources/lang/en/app.php b/packages/Webkul/Shop/src/Resources/lang/en/app.php index 13b6216bc..7c8d171eb 100644 --- a/packages/Webkul/Shop/src/Resources/lang/en/app.php +++ b/packages/Webkul/Shop/src/Resources/lang/en/app.php @@ -84,7 +84,8 @@ return [ 'order-summary' => 'Order Summary', 'shipping-address' => 'Shipping Address', 'use_for_shipping' => 'Ship to this address', - 'continue' => 'Continue' + 'continue' => 'Continue', + 'shipping-method' => 'Shipping Method' ] ] ]; \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Resources/views/checkout/onepage.blade.php b/packages/Webkul/Shop/src/Resources/views/checkout/onepage.blade.php index dbb4cb629..40a6ae6f7 100644 --- a/packages/Webkul/Shop/src/Resources/views/checkout/onepage.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/checkout/onepage.blade.php @@ -18,40 +18,28 @@
-
+
@include('shop::checkout.onepage.customer-info') @@ -65,15 +53,32 @@
-
+
+ + @include('shop::checkout.onepage.shipping') -
-
+
-
-
+ + +
+ +
+ +
+ + @include('shop::checkout.onepage.payment') + +
+ +
+ + @include('shop::checkout.onepage.review') + +
-
@include('shop::checkout.onepage.summary') @@ -89,10 +94,27 @@ inject: ['$validator'], data: () => ({ - billing: { - use_for_shipping: true + currentStep: 1, + + completedStep: 0, + + shipping_methods: [], + + payment_methods: [], + + address: { + billing: { + use_for_shipping: true + }, + + shipping: {}, }, - shipping: {}, + + selected_shipping_method: '', + + selected_payment: { + method: '' + } }), created () { @@ -100,19 +122,52 @@ }, methods: { + navigateToStep (step) { + if(step <= this.completedStep) { + this.currentStep = step + this.completedStep = step - 1; + } + }, + validateForm: function (scope) { this.$validator.validateAll(scope).then((result) => { if(result) { - this.saveAddress() + if(scope == 'address-form') { + this.saveAddress() + } else if(scope == 'shipping-form') { + this.saveShipping() + } } }); }, saveAddress () { + var this_this = this; + + this.$http.post("{{ route('shop.checkout.save-address') }}", this.address) + .then(function(response) { + if(response.data.shipping) { + this_this.shipping_methods = response.data.shipping + this_this.completedStep = 1; + this_this.currentStep = 2; + } + }) + }, + + saveShipping () { // this.$http.get('https://api.coindesk.com/v1/bpi/currentprice.json') // .then(function(response) { - // console.log(response) - // }) + this.completedStep = 2; + this.currentStep = 3; + // }) + }, + + savePayment () { + // this.$http.get('https://api.coindesk.com/v1/bpi/currentprice.json') + // .then(function(response) { + this.completedStep = 1; + this.currentStep = 2; + // }) } } }) diff --git a/packages/Webkul/Shop/src/Resources/views/checkout/onepage/customer-info.blade.php b/packages/Webkul/Shop/src/Resources/views/checkout/onepage/customer-info.blade.php index 9a0d01d2a..96642d85b 100644 --- a/packages/Webkul/Shop/src/Resources/views/checkout/onepage/customer-info.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/checkout/onepage/customer-info.blade.php @@ -15,7 +15,7 @@ {{ __('shop::app.checkout.onepage.first-name') }} - + @{{ errors.first('address-form.billing[first_name]') }} @@ -27,7 +27,7 @@ {{ __('shop::app.checkout.onepage.last-name') }} - + @{{ errors.first('address-form.billing[last_name]') }} @@ -39,7 +39,7 @@ {{ __('shop::app.checkout.onepage.email') }} - + @{{ errors.first('address-form.billing[email]') }} @@ -51,7 +51,7 @@ {{ __('shop::app.checkout.onepage.address1') }} - + @{{ errors.first('address-form.billing[address1]') }} @@ -63,7 +63,7 @@ {{ __('shop::app.checkout.onepage.address2') }} - +
@@ -71,7 +71,7 @@ {{ __('shop::app.checkout.onepage.city') }} - + @{{ errors.first('address-form.billing[city]') }} @@ -83,7 +83,7 @@ {{ __('shop::app.checkout.onepage.state') }} - + @{{ errors.first('address-form.billing[state]') }} @@ -95,7 +95,7 @@ {{ __('shop::app.checkout.onepage.postcode') }} - + @{{ errors.first('address-form.billing[postcode]') }} @@ -107,7 +107,7 @@ {{ __('shop::app.checkout.onepage.phone') }} - + @{{ errors.first('address-form.billing[phone]') }} @@ -119,7 +119,7 @@ {{ __('shop::app.checkout.onepage.country') }} - @foreach (country()->all() as $code => $country) @@ -136,7 +136,7 @@
- + {{ __('shop::app.checkout.onepage.use_for_shipping') }} @@ -144,7 +144,7 @@
-
+

{{ __('shop::app.checkout.onepage.shipping-address') }}

@@ -155,7 +155,7 @@ {{ __('shop::app.checkout.onepage.first-name') }} - + @{{ errors.first('address-form.shipping[first_name]') }} @@ -167,7 +167,7 @@ {{ __('shop::app.checkout.onepage.last-name') }} - + @{{ errors.first('address-form.shipping[last_name]') }} @@ -179,7 +179,7 @@ {{ __('shop::app.checkout.onepage.email') }} - + @{{ errors.first('address-form.shipping[email]') }} @@ -191,7 +191,7 @@ {{ __('shop::app.checkout.onepage.address1') }} - + @{{ errors.first('address-form.shipping[address1]') }} @@ -203,7 +203,7 @@ {{ __('shop::app.checkout.onepage.address2') }} - +
@@ -211,7 +211,7 @@ {{ __('shop::app.checkout.onepage.city') }} - + @{{ errors.first('address-form.shipping[city]') }} @@ -223,7 +223,7 @@ {{ __('shop::app.checkout.onepage.state') }} - + @{{ errors.first('address-form.shipping[state]') }} @@ -235,7 +235,7 @@ {{ __('shop::app.checkout.onepage.postcode') }} - + @{{ errors.first('address-form.shipping[postcode]') }} @@ -247,7 +247,7 @@ {{ __('shop::app.checkout.onepage.phone') }} - + @{{ errors.first('address-form.shipping[phone]') }} @@ -259,7 +259,7 @@ {{ __('shop::app.checkout.onepage.country') }} - @foreach (country()->all() as $code => $country) diff --git a/packages/Webkul/Shop/src/Resources/views/checkout/onepage/shipping.blade.php b/packages/Webkul/Shop/src/Resources/views/checkout/onepage/shipping.blade.php index e69de29bb..a9c0800e9 100644 --- a/packages/Webkul/Shop/src/Resources/views/checkout/onepage/shipping.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/checkout/onepage/shipping.blade.php @@ -0,0 +1,26 @@ +
+
+
+

{{ __('shop::app.checkout.onepage.shipping-method') }}

+
+ +
+ +
+

@{{ shipping_method.carrier_title }}

+ + + + + @{{ rate.method_title }} + @{{ rate.price_formated }} + + + + @{{ errors.first('shipping-form.shipping_method') }} + +
+ +
+
+
\ No newline at end of file diff --git a/packages/Webkul/Shop/src/Resources/views/customers/account/reviews/reviews.blade.php b/packages/Webkul/Shop/src/Resources/views/customers/account/reviews/reviews.blade.php index 3f4fd72c8..60cdced18 100644 --- a/packages/Webkul/Shop/src/Resources/views/customers/account/reviews/reviews.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/customers/account/reviews/reviews.blade.php @@ -1 +1,44 @@ -

Customer Reviews page

\ No newline at end of file +@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage') + +@extends('shop::layouts.master') +@section('content-wrapper') + +@endsection \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Resources/views/layouts/header/index.blade.php b/packages/Webkul/Shop/src/Resources/views/layouts/header/index.blade.php index 0fdee9e33..72fa0b8da 100644 --- a/packages/Webkul/Shop/src/Resources/views/layouts/header/index.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/layouts/header/index.blade.php @@ -91,7 +91,19 @@ - + @if(isset($cart)) + + @else +
    +
  • + + + 0Products + + +
  • +
+ @endif {{-- Meant for responsive views only --}}
    diff --git a/packages/Webkul/Shop/src/Resources/views/products/view.blade.php b/packages/Webkul/Shop/src/Resources/views/products/view.blade.php index d601c4b38..b8d8a930f 100644 --- a/packages/Webkul/Shop/src/Resources/views/products/view.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/products/view.blade.php @@ -8,15 +8,13 @@ @section('content-wrapper')
    - Home > Men > Slit Open Jeans -
    @csrf() - + @include ('shop::products.view.gallery') @@ -37,6 +35,17 @@ {{ $product->short_description }}
    +
    + + +
    + + @if ($product->type == 'configurable') + + @else + + @endif + @include ('shop::products.view.configurable-options') diff --git a/packages/Webkul/Shop/src/Resources/views/products/view/reviews.blade.php b/packages/Webkul/Shop/src/Resources/views/products/view/reviews.blade.php index 1e9cb3a92..f877278f7 100644 --- a/packages/Webkul/Shop/src/Resources/views/products/view/reviews.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/products/view/reviews.blade.php @@ -1,5 +1,4 @@ @inject ('reviewHelper', 'Webkul\Product\Product\Review') - @if ($total = $reviewHelper->getTotalReviews($product))
    @@ -27,15 +26,17 @@
    + @if(!is_null($customer)) {{ __('shop::app.products.write-review-btn') }} + @endif
    - @foreach ($reviewHelper->getReviews($product)->paginate(5) as $review) + @foreach ($reviewHelper->getReviews($product)->paginate(10) as $review)
    {{ $review->title }} diff --git a/public/themes/default/assets/css/shop.css b/public/themes/default/assets/css/shop.css index 7b72e4fcd..1c4f7922c 100644 --- a/public/themes/default/assets/css/shop.css +++ b/public/themes/default/assets/css/shop.css @@ -1132,7 +1132,6 @@ section.slider-block div.slider-content div.slider-control .light-right-icon { .main-container-wrapper .product-card .cart-fav-seg .addtocart { white-space: nowrap; font-size: 12px; - border-radius: 0px; } .main-container-wrapper .top-toolbar { border-bottom: 1px solid #E8E8E8; @@ -1198,7 +1197,6 @@ section.slider-block div.slider-content div.slider-control .light-right-icon { .main-container-wrapper .product-card .cart-fav-seg .addtocart { white-space: nowrap; font-size: 12px; - border-radius: 0px; } .main-container-wrapper .top-toolbar { border-bottom: 1px solid #E8E8E8; @@ -1694,13 +1692,11 @@ section.product-detail div.layouter form div.product-image-group .cart-fav-seg { section.product-detail div.layouter form div.product-image-group .cart-fav-seg .addtocart { width: 293px; background: black; - border-radius: 0px; } section.product-detail div.layouter form div.product-image-group .cart-fav-seg .buynow { width: 293px; float: right; - border-radius: 0px; } section.product-detail div.layouter form .details { @@ -1909,11 +1905,9 @@ section.product-detail div.layouter form .details .full-description { section.product-detail div.layouter form .details .attributes .cart-fav-seg .addtocart { width: 49%; background: #000000; - border-radius: 0px; } section.product-detail div.layouter form .details .attributes .cart-fav-seg .buynow { width: 49%; - border-radius: 0px; } } @@ -3975,3 +3969,57 @@ section.review .review-layouter .review-info .review-detail .rating-calculate .p width: 20px; border: 1px solid blue; } + +.cusomer-section { + margin-left: 50px; + width: 100%; +} + +.cusomer-section .customer-section-info { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + border-top: 1px solid #E8E8E8; +} + +.cusomer-section .customer-section-info .pro-img { + margin-top: 10px; + margin-bottom: 5px; +} + +.cusomer-section .customer-section-info .pro-img img { + height: 125px; + width: 100px; +} + +.cusomer-section .customer-section-info .pro-discription { + margin-left: 20px; + width: 100%; +} + +.cusomer-section .customer-section-info .pro-discription .title { + font-size: 16px; + color: #0031F0; + margin-top: 15px; +} + +.cusomer-section .customer-section-info .pro-discription .rating { + margin-top: 10px; +} + +.cusomer-section .customer-section-info .pro-discription .rating .icon { + height: 16px; + width: 16px; +} + +.cusomer-section .customer-section-info .pro-discription .discription { + margin-top: 15px; +} + +.cusomer-section .customer-section-info:last-child { + border-bottom: 1px solid #e8e8e8; +} diff --git a/public/themes/default/assets/js/shop.js b/public/themes/default/assets/js/shop.js index 30714e42d..21a1e4405 100644 --- a/public/themes/default/assets/js/shop.js +++ b/public/themes/default/assets/js/shop.js @@ -60,34 +60,317 @@ /******/ __webpack_require__.p = "/"; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 2); +/******/ return __webpack_require__(__webpack_require__.s = 12); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ -/***/ (function(module, exports) { +/***/ (function(module, exports, __webpack_require__) { -var g; +"use strict"; -// This works in non-strict mode -g = (function() { - return this; -})(); -try { - // This works if eval is allowed (see CSP) - g = g || Function("return this")() || (1,eval)("this"); -} catch(e) { - // This works if the window reference is available - if(typeof window === "object") - g = window; +var bind = __webpack_require__(5); +var isBuffer = __webpack_require__(21); + +/*global toString:true*/ + +// utils is a library of generic helper functions non-specific to axios + +var toString = Object.prototype.toString; + +/** + * Determine if a value is an Array + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Array, otherwise false + */ +function isArray(val) { + return toString.call(val) === '[object Array]'; } -// g can still be undefined, but nothing to do about it... -// We return undefined, instead of nothing here, so it's -// easier to handle this case. if(!global) { ...} +/** + * Determine if a value is an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an ArrayBuffer, otherwise false + */ +function isArrayBuffer(val) { + return toString.call(val) === '[object ArrayBuffer]'; +} -module.exports = g; +/** + * Determine if a value is a FormData + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an FormData, otherwise false + */ +function isFormData(val) { + return (typeof FormData !== 'undefined') && (val instanceof FormData); +} + +/** + * Determine if a value is a view on an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + */ +function isArrayBufferView(val) { + var result; + if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { + result = ArrayBuffer.isView(val); + } else { + result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); + } + return result; +} + +/** + * Determine if a value is a String + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a String, otherwise false + */ +function isString(val) { + return typeof val === 'string'; +} + +/** + * Determine if a value is a Number + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Number, otherwise false + */ +function isNumber(val) { + return typeof val === 'number'; +} + +/** + * Determine if a value is undefined + * + * @param {Object} val The value to test + * @returns {boolean} True if the value is undefined, otherwise false + */ +function isUndefined(val) { + return typeof val === 'undefined'; +} + +/** + * Determine if a value is an Object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Object, otherwise false + */ +function isObject(val) { + return val !== null && typeof val === 'object'; +} + +/** + * Determine if a value is a Date + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Date, otherwise false + */ +function isDate(val) { + return toString.call(val) === '[object Date]'; +} + +/** + * Determine if a value is a File + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a File, otherwise false + */ +function isFile(val) { + return toString.call(val) === '[object File]'; +} + +/** + * Determine if a value is a Blob + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Blob, otherwise false + */ +function isBlob(val) { + return toString.call(val) === '[object Blob]'; +} + +/** + * Determine if a value is a Function + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Function, otherwise false + */ +function isFunction(val) { + return toString.call(val) === '[object Function]'; +} + +/** + * Determine if a value is a Stream + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Stream, otherwise false + */ +function isStream(val) { + return isObject(val) && isFunction(val.pipe); +} + +/** + * Determine if a value is a URLSearchParams object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ +function isURLSearchParams(val) { + return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; +} + +/** + * Trim excess whitespace off the beginning and end of a string + * + * @param {String} str The String to trim + * @returns {String} The String freed of excess whitespace + */ +function trim(str) { + return str.replace(/^\s*/, '').replace(/\s*$/, ''); +} + +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + */ +function isStandardBrowserEnv() { + if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { + return false; + } + return ( + typeof window !== 'undefined' && + typeof document !== 'undefined' + ); +} + +/** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + */ +function forEach(obj, fn) { + // Don't bother if no value provided + if (obj === null || typeof obj === 'undefined') { + return; + } + + // Force an array if not already something iterable + if (typeof obj !== 'object') { + /*eslint no-param-reassign:0*/ + obj = [obj]; + } + + if (isArray(obj)) { + // Iterate over array values + for (var i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + // Iterate over object keys + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + fn.call(null, obj[key], key, obj); + } + } + } +} + +/** + * Accepts varargs expecting each argument to be an object, then + * immutably merges the properties of each object and returns result. + * + * When multiple objects contain the same key the later object in + * the arguments list will take precedence. + * + * Example: + * + * ```js + * var result = merge({foo: 123}, {foo: 456}); + * console.log(result.foo); // outputs 456 + * ``` + * + * @param {Object} obj1 Object to merge + * @returns {Object} Result of all merge properties + */ +function merge(/* obj1, obj2, obj3, ... */) { + var result = {}; + function assignValue(val, key) { + if (typeof result[key] === 'object' && typeof val === 'object') { + result[key] = merge(result[key], val); + } else { + result[key] = val; + } + } + + for (var i = 0, l = arguments.length; i < l; i++) { + forEach(arguments[i], assignValue); + } + return result; +} + +/** + * Extends object a by mutably adding to it the properties of object b. + * + * @param {Object} a The object to be extended + * @param {Object} b The object to copy properties from + * @param {Object} thisArg The object to bind function to + * @return {Object} The resulting value of object a + */ +function extend(a, b, thisArg) { + forEach(b, function assignValue(val, key) { + if (thisArg && typeof val === 'function') { + a[key] = bind(val, thisArg); + } else { + a[key] = val; + } + }); + return a; +} + +module.exports = { + isArray: isArray, + isArrayBuffer: isArrayBuffer, + isBuffer: isBuffer, + isFormData: isFormData, + isArrayBufferView: isArrayBufferView, + isString: isString, + isNumber: isNumber, + isObject: isObject, + isUndefined: isUndefined, + isDate: isDate, + isFile: isFile, + isBlob: isBlob, + isFunction: isFunction, + isStream: isStream, + isURLSearchParams: isURLSearchParams, + isStandardBrowserEnv: isStandardBrowserEnv, + forEach: forEach, + merge: merge, + extend: extend, + trim: trim +}; /***/ }), @@ -201,29 +484,928 @@ module.exports = function normalizeComponent ( /***/ }), /* 2 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, exports) { -__webpack_require__(3); -module.exports = __webpack_require__(25); +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { -window.jQuery = window.$ = $ = __webpack_require__(4); -window.Vue = __webpack_require__(5); -window.VeeValidate = __webpack_require__(9); -window.axios = __webpack_require__(36); +"use strict"; +/* WEBPACK VAR INJECTION */(function(process) { + +var utils = __webpack_require__(0); +var normalizeHeaderName = __webpack_require__(23); + +var DEFAULT_CONTENT_TYPE = { + 'Content-Type': 'application/x-www-form-urlencoded' +}; + +function setContentTypeIfUnset(headers, value) { + if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { + headers['Content-Type'] = value; + } +} + +function getDefaultAdapter() { + var adapter; + if (typeof XMLHttpRequest !== 'undefined') { + // For browsers use XHR adapter + adapter = __webpack_require__(6); + } else if (typeof process !== 'undefined') { + // For node use HTTP adapter + adapter = __webpack_require__(6); + } + return adapter; +} + +var defaults = { + adapter: getDefaultAdapter(), + + transformRequest: [function transformRequest(data, headers) { + normalizeHeaderName(headers, 'Content-Type'); + if (utils.isFormData(data) || + utils.isArrayBuffer(data) || + utils.isBuffer(data) || + utils.isStream(data) || + utils.isFile(data) || + utils.isBlob(data) + ) { + return data; + } + if (utils.isArrayBufferView(data)) { + return data.buffer; + } + if (utils.isURLSearchParams(data)) { + setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); + return data.toString(); + } + if (utils.isObject(data)) { + setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); + return JSON.stringify(data); + } + return data; + }], + + transformResponse: [function transformResponse(data) { + /*eslint no-param-reassign:0*/ + if (typeof data === 'string') { + try { + data = JSON.parse(data); + } catch (e) { /* Ignore */ } + } + return data; + }], + + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + maxContentLength: -1, + + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + } +}; + +defaults.headers = { + common: { + 'Accept': 'application/json, text/plain, */*' + } +}; + +utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { + defaults.headers[method] = {}; +}); + +utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); +}); + +module.exports = defaults; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function bind(fn, thisArg) { + return function wrap() { + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + return fn.apply(thisArg, args); + }; +}; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var utils = __webpack_require__(0); +var settle = __webpack_require__(24); +var buildURL = __webpack_require__(26); +var parseHeaders = __webpack_require__(27); +var isURLSameOrigin = __webpack_require__(28); +var createError = __webpack_require__(7); +var btoa = (typeof window !== 'undefined' && window.btoa && window.btoa.bind(window)) || __webpack_require__(29); + +module.exports = function xhrAdapter(config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + var requestData = config.data; + var requestHeaders = config.headers; + + if (utils.isFormData(requestData)) { + delete requestHeaders['Content-Type']; // Let the browser set it + } + + var request = new XMLHttpRequest(); + var loadEvent = 'onreadystatechange'; + var xDomain = false; + + // For IE 8/9 CORS support + // Only supports POST and GET calls and doesn't returns the response headers. + // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest. + if ("development" !== 'test' && + typeof window !== 'undefined' && + window.XDomainRequest && !('withCredentials' in request) && + !isURLSameOrigin(config.url)) { + request = new window.XDomainRequest(); + loadEvent = 'onload'; + xDomain = true; + request.onprogress = function handleProgress() {}; + request.ontimeout = function handleTimeout() {}; + } + + // HTTP basic authentication + if (config.auth) { + var username = config.auth.username || ''; + var password = config.auth.password || ''; + requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); + } + + request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true); + + // Set the request timeout in MS + request.timeout = config.timeout; + + // Listen for ready state + request[loadEvent] = function handleLoad() { + if (!request || (request.readyState !== 4 && !xDomain)) { + return; + } + + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + + // Prepare the response + var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; + var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; + var response = { + data: responseData, + // IE sends 1223 instead of 204 (https://github.com/axios/axios/issues/201) + status: request.status === 1223 ? 204 : request.status, + statusText: request.status === 1223 ? 'No Content' : request.statusText, + headers: responseHeaders, + config: config, + request: request + }; + + settle(resolve, reject, response); + + // Clean up request + request = null; + }; + + // Handle low level network errors + request.onerror = function handleError() { + // Real errors are hidden from us by the browser + // onerror should only fire if it's a network error + reject(createError('Network Error', config, null, request)); + + // Clean up request + request = null; + }; + + // Handle timeout + request.ontimeout = function handleTimeout() { + reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', + request)); + + // Clean up request + request = null; + }; + + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + if (utils.isStandardBrowserEnv()) { + var cookies = __webpack_require__(30); + + // Add xsrf header + var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? + cookies.read(config.xsrfCookieName) : + undefined; + + if (xsrfValue) { + requestHeaders[config.xsrfHeaderName] = xsrfValue; + } + } + + // Add headers to the request + if ('setRequestHeader' in request) { + utils.forEach(requestHeaders, function setRequestHeader(val, key) { + if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { + // Remove Content-Type if data is undefined + delete requestHeaders[key]; + } else { + // Otherwise add header to the request + request.setRequestHeader(key, val); + } + }); + } + + // Add withCredentials to request if needed + if (config.withCredentials) { + request.withCredentials = true; + } + + // Add responseType to request if needed + if (config.responseType) { + try { + request.responseType = config.responseType; + } catch (e) { + // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. + // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. + if (config.responseType !== 'json') { + throw e; + } + } + } + + // Handle progress if needed + if (typeof config.onDownloadProgress === 'function') { + request.addEventListener('progress', config.onDownloadProgress); + } + + // Not all browsers support upload events + if (typeof config.onUploadProgress === 'function' && request.upload) { + request.upload.addEventListener('progress', config.onUploadProgress); + } + + if (config.cancelToken) { + // Handle cancellation + config.cancelToken.promise.then(function onCanceled(cancel) { + if (!request) { + return; + } + + request.abort(); + reject(cancel); + // Clean up request + request = null; + }); + } + + if (requestData === undefined) { + requestData = null; + } + + // Send the request + request.send(requestData); + }); +}; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var enhanceError = __webpack_require__(25); + +/** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {Object} config The config. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The created error. + */ +module.exports = function createError(message, config, code, request, response) { + var error = new Error(message); + return enhanceError(error, config, code, request, response); +}; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function isCancel(value) { + return !!(value && value.__CANCEL__); +}; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * A `Cancel` is an object that is thrown when an operation is canceled. + * + * @class + * @param {string=} message The message. + */ +function Cancel(message) { + this.message = message; +} + +Cancel.prototype.toString = function toString() { + return 'Cancel' + (this.message ? ': ' + this.message : ''); +}; + +Cancel.prototype.__CANCEL__ = true; + +module.exports = Cancel; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +// css base code, injected by the css-loader +module.exports = function(useSourceMap) { + var list = []; + + // return the list of modules as css string + list.toString = function toString() { + return this.map(function (item) { + var content = cssWithMappingToString(item, useSourceMap); + if(item[2]) { + return "@media " + item[2] + "{" + content + "}"; + } else { + return content; + } + }).join(""); + }; + + // import a list of modules into the list + list.i = function(modules, mediaQuery) { + if(typeof modules === "string") + modules = [[null, modules, ""]]; + var alreadyImportedModules = {}; + for(var i = 0; i < this.length; i++) { + var id = this[i][0]; + if(typeof id === "number") + alreadyImportedModules[id] = true; + } + for(i = 0; i < modules.length; i++) { + var item = modules[i]; + // skip already imported module + // this implementation is not 100% perfect for weird media query combinations + // when a module is imported multiple times with different media queries. + // I hope this will never occur (Hey this way we have smaller bundles) + if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { + if(mediaQuery && !item[2]) { + item[2] = mediaQuery; + } else if(mediaQuery) { + item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; + } + list.push(item); + } + } + }; + return list; +}; + +function cssWithMappingToString(item, useSourceMap) { + var content = item[1] || ''; + var cssMapping = item[3]; + if (!cssMapping) { + return content; + } + + if (useSourceMap && typeof btoa === 'function') { + var sourceMapping = toComment(cssMapping); + var sourceURLs = cssMapping.sources.map(function (source) { + return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' + }); + + return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); + } + + return [content].join('\n'); +} + +// Adapted from convert-source-map (MIT) +function toComment(sourceMap) { + // eslint-disable-next-line no-undef + var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); + var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; + + return '/*# ' + data + ' */'; +} + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + Modified by Evan You @yyx990803 +*/ + +var hasDocument = typeof document !== 'undefined' + +if (typeof DEBUG !== 'undefined' && DEBUG) { + if (!hasDocument) { + throw new Error( + 'vue-style-loader cannot be used in a non-browser environment. ' + + "Use { target: 'node' } in your Webpack config to indicate a server-rendering environment." + ) } +} + +var listToStyles = __webpack_require__(47) + +/* +type StyleObject = { + id: number; + parts: Array +} + +type StyleObjectPart = { + css: string; + media: string; + sourceMap: ?string +} +*/ + +var stylesInDom = {/* + [id: number]: { + id: number, + refs: number, + parts: Array<(obj?: StyleObjectPart) => void> + } +*/} + +var head = hasDocument && (document.head || document.getElementsByTagName('head')[0]) +var singletonElement = null +var singletonCounter = 0 +var isProduction = false +var noop = function () {} +var options = null +var ssrIdKey = 'data-vue-ssr-id' + +// Force single-tag solution on IE6-9, which has a hard limit on the # of