This commit is contained in:
rahul shukla 2018-10-08 10:01:17 +05:30
commit 05a4f84882
55 changed files with 1195 additions and 390 deletions

View File

@ -6,7 +6,7 @@ return [
'title' => 'Cash On Delivery',
'description' => 'Cash On Delivery',
'class' => 'Webkul\Payment\Payment\CashOnDelivery',
'order_status' => 'Pending',
'order_status' => 'pending',
'active' => true
],
@ -15,7 +15,7 @@ return [
'title' => 'Money Transfer',
'description' => 'Money Transfer',
'class' => 'Webkul\Payment\Payment\MoneyTransfer',
'order_status' => 'Pending',
'order_status' => 'pending',
'active' => true
]
];

View File

@ -83,7 +83,7 @@ class Cart {
}
/**
* Prepare the other data for the product to be added.
* Prepare the other data for the product to be success.
*
* @param integer $id
* @param array $data
@ -96,14 +96,14 @@ class Cart {
unset($data['_token']);
//Check if the product is salable
//Check if the product is saleable
if(!isset($data['product']) ||!isset($data['quantity'])) {
session()->flash('error', 'Cart System Integrity Violation, Some Required Fields Missing.');
session()->flash('error', trans('shop::app.checkout.cart.integrity.missing_fields'));
return redirect()->back();
} else {
if($product->type == 'configurable' && !isset($data['super_attribute'])) {
session()->flash('error', 'Cart System Integrity Violation, Configurable Options Not Found In Request.');
session()->flash('error', trans('shop::app.checkout.cart.integrity.missing_options'));
return redirect()->back();
}
@ -153,13 +153,13 @@ class Cart {
'total_weight' => $product->weight * $data['quantity'],
'base_total_weight' => $product->weight * $data['quantity'],
];
return ['parent' => $parentData, 'child' => null];
}
}
/**
* Create new cart instance with the current item added.
* Create new cart instance with the current item success.
*
* @param integer $id
* @param array $data
@ -172,13 +172,15 @@ class Cart {
$cartData['channel_id'] = core()->getCurrentChannel()->id;
// this will auto set the customer id for the cart instances if customer is authenticated
//auth user details else they will be set when the customer is guest
if(auth()->guard('customer')->check()) {
$cartData['customer_id'] = auth()->guard('customer')->user()->id;
$cartData['is_guest'] = 0;
$cartData['customer_full_name'] = auth()->guard('customer')->user()->first_name .' '. auth()->guard('customer')->user()->last_name;
$cartData['customer_first_name'] = auth()->guard('customer')->user()->first_name;
$cartData['customer_last_name'] = auth()->guard('customer')->user()->last_name;
} else {
$cartData['is_guest'] = 1;
}
@ -190,43 +192,38 @@ class Cart {
if($cart = $this->cart->create($cartData)) {
$itemData['parent']['cart_id'] = $cart->id;
if ($data['is_configurable'] == "true") {
//parent product entry
if ($this->product->find($id)->type == "configurable") {
//parent item entry
$itemData['parent']['additional'] = json_encode($data);
if($parent = $this->cartItem->create($itemData['parent'])) {
//child item entry
$itemData['child']['parent_id'] = $parent->id;
$itemData['child']['cart_id'] = $cart->id;
if($child = $this->cartItem->create($itemData['child'])) {
session()->put('cart', $cart);
session()->flash('success', 'Item Added To Cart Successfully');
session()->flash('success', trans('shop::app.checkout.cart.item.success'));
$this->collectTotals();
return redirect()->back();
}
}
// $cart->update(['subtotal' => $itemData['parent']['price'], 'base_sub_total' => $itemData['parent']['price']]);
$this->collectQuantities();
$this->collectTotals();
} else if($data['is_configurable'] == "false") {
} else if($this->product->find($id)->type != "configurable") {
if($result = $this->cartItem->create($itemData['parent'])) {
session()->put('cart', $cart);
session()->flash('success', 'Item Added To Cart Successfully');
session()->flash('success', trans('shop::app.checkout.cart.item.success'));
$this->collectTotals();
return redirect()->back();
}
// $cart->update(['subtotal' => $itemData['parent']['price'], 'base_sub_total' => $itemData['parent']['price']]);
$this->collectQuantities();
$this->collectTotals();
}
}
session()->flash('error', 'Some Error Occured');
session()->flash('error', trans('shop::app.checkout.cart.item.error_add'));
return redirect()->back();
}
@ -238,10 +235,35 @@ class Cart {
*/
public function getCart()
{
if(!$cart = session()->get('cart'))
return false;
$cart = null;
return $this->cart->find($cart->id);
if(session()->has('cart')) {
$cart = $this->cart->find(session()->get('cart')->id);
} else if(auth()->guard('customer')->check()) {
$cart = $this->cart->findOneByField('customer_id', auth()->guard('customer')->user()->id);
}
return $cart && $cart->is_active ? $cart : null;
}
/**
* Returns cart details in array
*
* @return array
*/
public function toArray()
{
$cart = $this->getCart();
$data = $cart->toArray();
$data['shipping_address'] = current($data['shipping_address']);
$data['billing_address'] = current($data['billing_address']);
$data['selected_shipping_rate'] = $cart->selected_shipping_rate->toArray();
return $data;
}
/**
@ -269,12 +291,12 @@ class Cart {
}
if ($quantity < 1) {
session()->flash('warning', 'Cannot Add Or Update Lesser than 1');
session()->flash('warning', trans('shop::app.checkout.cart.quantity.warning'));
return redirect()->back();
}
if($quantity < $totalQty) {
if($quantity <= $totalQty) {
return true;
} else {
return false;
@ -294,13 +316,13 @@ class Cart {
$itemData = $this->prepareItemData($id, $data);
if(session()->has('cart')) {
$cart = session()->get('cart');
$cart = $this->getCart();
$cartItems = $cart->items()->get();
if(isset($cartItems)) {
foreach($cartItems as $cartItem) {
if($data['is_configurable'] == "false") {
if($this->product->find($id)->type == "simple") {
if($cartItem->product_id == $id) {
$prevQty = $cartItem->quantity;
@ -309,7 +331,7 @@ class Cart {
$canBe = $this->canAddOrUpdate($cartItem->id, $prevQty + $newQty);
if($canBe == false) {
session()->flash('warning', 'The requested quantity is not available, please try back later.');
session()->flash('warning', trans('shop::app.checkout.cart.quantity.inventory_warning'));
return redirect()->back();
}
@ -320,15 +342,13 @@ class Cart {
'base_total' => $cartItem->price * ($prevQty + $newQty)
]);
$this->collectQuantities();
$this->collectTotals();
session()->flash('success', "Product Quantity Successfully Updated");
session()->flash('success', trans('shop::app.checkout.cart.quantity.success'));
return redirect()->back();
}
} else if($data['is_configurable'] == "true") {
} else if($this->product->find($id)->type == "configurable") {
if($cartItem->type == "configurable") {
$temp = $this->cartItem->findOneByField('parent_id', $cartItem->id);
if($temp->product_id == $data['selected_configurable_option']) {
@ -343,7 +363,7 @@ class Cart {
$canBe = $this->canAddOrUpdate($cartItem->child->id, $prevQty + $newQty);
if($canBe == false) {
session()->flash('warning', 'The requested quantity is not available, please try back later.');
session()->flash('warning', trans('shop::app.checkout.cart.quantity.inventory_warning'));
return redirect()->back();
}
@ -354,11 +374,9 @@ class Cart {
'base_total' => $parentPrice * ($prevQty + $newQty)
]);
$this->collectQuantities();
$this->collectTotals();
session()->flash('success', "Product Quantity Successfully Updated");
session()->flash('success', trans('shop::app.checkout.cart.quantity.success'));
return redirect()->back();
}
@ -366,7 +384,7 @@ class Cart {
}
}
if($data['is_configurable'] == "true") {
if($this->product->find($id)->type == "configurable") {
$parent = $cart->items()->create($itemData['parent']);
$itemData['child']['parent_id'] = $parent->id;
@ -374,17 +392,15 @@ class Cart {
// $this->canAddOrUpdate($parent->child->id, $parent->quantity);
$cart->items()->create($itemData['child']);
} else if($data['is_configurable'] == "false"){
} else if($this->product->find($id)->type != "configurable"){
// $this->canAddOrUpdate($parent->id, $parent->quantity);
$parent = $cart->items()->create($itemData['parent']);
}
$this->collectQuantities();
$this->collectTotals();
session()->flash('success', 'Item Successfully Added To Cart');
session()->flash('success', trans('shop::app.checkout.cart.item.success'));
return redirect()->back();
} else {
@ -406,7 +422,7 @@ class Cart {
public function update($itemIds)
{
if(session()->has('cart')) {
$cart = session()->get('cart');
$cart = $this->getCart();
$items = $cart->items;
@ -420,19 +436,18 @@ class Cart {
}
if($canBe == false) {
session()->flash('warning', 'The requested quantity is not available, please try back later.');
session()->flash('warning', trans('shop::app.checkout.cart.quantity.inventory_warning'));
return redirect()->back();
}
$item->update(['quantity' => $quantity]);
$this->collectTotals();
}
}
}
$items = $cart->items;
session()->flash('success', 'Cart Updated Successfully');
session()->flash('success', trans('shop::app.checkout.cart.quantity.success'));
return redirect()->back();
}
@ -445,9 +460,8 @@ class Cart {
*/
public function removeItem($itemId)
{
dd($itemId);
if(session()->has('cart')) {
$cart = session()->get('cart');
$cart = $this->getCart();
$items = $cart->items;
@ -461,12 +475,10 @@ class Cart {
if($result)
$result = $this->cartItem->delete($item->id);
$this->collectQuantities();
$this->collectTotals();
} else if($item->type == "simple" && $item->parent_id == null){
$result = $this->cartItem->delete($item->id);
$this->collectQuantities();
$this->collectTotals();
}
}
@ -485,13 +497,11 @@ class Cart {
}
if ($result) {
session()->flash('sucess', trans('shop::app.checkout.cart.remove.success'));
session()->flash('sucess', trans('shop::app.checkout.cart.quantity.success_remove'));
} else {
session()->flash('error', trans('shop::app.checkout.cart.remove.error'));
session()->flash('error', trans('shop::app.checkout.cart.quantity.error_remove'));
}
}
session()->flash('warning', trans('shop::app.checkout.cart.remove.cannot'));
return redirect()->back();
}
@ -536,7 +546,7 @@ class Cart {
$shippingAddress = $data['shipping'];
$billingAddress['cart_id'] = $shippingAddress['cart_id'] = $cart->id;
if($billingAddressModel = $cart->biling_address) {
if($billingAddressModel = $cart->billing_address) {
$this->cartAddress->update($billingAddress, $billingAddressModel->id);
if($shippingAddress = $cart->shipping_address) {
@ -611,28 +621,6 @@ class Cart {
return $cartPayment;
}
/**
* Update Cart Quantities, Weight
*
* @return void
*/
public function collectQuantities()
{
if(!$cart = $this->getCart())
return false;
$quantities = 0;
foreach($cart->items as $item) {
$quantities = $quantities + $item->quantity;
}
$itemCount = $cart->items->count();
$cart->update(['items_count' => $itemCount, 'items_qty' => $quantities]);
}
/**
* Updates cart totals
*
@ -651,8 +639,8 @@ class Cart {
$cart->base_sub_total_with_discount = 0;
foreach ($cart->items()->get() as $item) {
$cart->grand_total = (float) $cart->grand_total + $item->price * $item->quantity;
$cart->base_grand_total = (float) $cart->base_grand_total + $item->base_price * $item->quantity;
$cart->grand_total = (float) $cart->grand_total + $item->total;
$cart->base_grand_total = (float) $cart->base_grand_total + $item->base_total;
$cart->sub_total = (float) $cart->sub_total + $item->price * $item->quantity;
$cart->base_sub_total = (float) $cart->base_sub_total + $item->base_price * $item->quantity;
@ -663,6 +651,15 @@ class Cart {
$cart->base_grand_total = (float) $cart->base_grand_total + $shipping->base_price;
}
$quantities = 0;
foreach($cart->items as $item) {
$quantities = $quantities + $item->quantity;
}
$cart->items_count = $cart->items->count();
$cart->items_qty = $quantities;
$cart->save();
}
@ -676,10 +673,10 @@ class Cart {
if(session()->has('cart')) {
$cart = $this->cart->findOneByField('customer_id', auth()->guard('customer')->user()->id);
$guestCart = session()->get('cart');
$guestCart = $this->getCart();
if(!isset($cart)) {
$guestCart->update(['customer_id' => auth()->guard('customer')->user()->id]);
$guestCart->update(['customer_id' => auth()->guard('customer')->user()->id, 'is_guest' => 0]);
session()->forget('cart');
@ -780,8 +777,6 @@ class Cart {
//put the customer cart instance
session()->put('cart', $cart);
$this->collectQuantities();
$this->collectTotals();
return redirect()->back();
@ -791,9 +786,7 @@ class Cart {
}
/**
* Destroys the session
* maintained for cart
* on customer logout.
* Destroys the session maintained for cart on customer logout.
*
* @return response
*/
@ -807,4 +800,140 @@ class Cart {
return redirect()->back();
}
}
/**
* Checks if cart has any error
*
* @return boolean
*/
public function hasError()
{
if(!$this->getCart())
return true;
if(!$this->isItemsHaveSufficientQuantity())
return true;
return false;
}
/**
* Checks if all cart items have sufficient quantity.
*
* @return boolean
*/
public function isItemsHaveSufficientQuantity()
{
foreach ($this->getCart()->items as $item) {
if(!$this->isItemHaveQuantity($item))
return false;
}
return true;
}
/**
* Checks if all cart items have sufficient quantity.
*
* @return boolean
*/
public function isItemHaveQuantity($item)
{
$product = $item->type == 'configurable' ? $item->child->product : $item->product;
if(!$product->haveSufficientQuantity($item->quantity))
return false;
return true;
}
/**
* Deactivates current cart
*
* @return void
*/
public function deActivateCart()
{
if($cart = $this->getCart()) {
$this->cart->update(['is_active' => false], $cart->id);
if(session()->has('cart')) {
session()->forget('cart');
}
}
}
/**
* Validate order before creation
*
* @return array
*/
public function prepareDataForOrder()
{
$data = $this->toArray();
$finalData = [
'customer_id' => $data['customer_id'],
'is_guest' => $data['is_guest'],
'customer_email' => $data['customer_email'],
'customer_first_name' => $data['customer_first_name'],
'customer_last_name' => $data['customer_last_name'],
'customer' => auth()->guard('customer')->check() ? auth()->guard('customer')->user : null,
'shipping_method' => $data['selected_shipping_rate']['method'],
'shipping_description' => $data['selected_shipping_rate']['method_description'],
'shipping_amount' => $data['selected_shipping_rate']['price'],
'base_shipping_amount' => $data['selected_shipping_rate']['base_price'],
'total_item_count' => $data['items_count'],
'total_qty_ordered' => $data['items_qty'],
'base_currency_code' => $data['base_currency_code'],
'channel_currency_code' => $data['channel_currency_code'],
'order_currency_code' => $data['cart_currency_code'],
'grand_total' => $data['grand_total'],
'base_grand_total' => $data['base_grand_total'],
'sub_total' => $data['sub_total'],
'base_sub_total' => $data['base_sub_total'],
'shipping_address' => array_except($data['shipping_address'], ['id', 'cart_id']),
'billing_address' => array_except($data['billing_address'], ['id', 'cart_id']),
'payment' => array_except($data['payment'], ['id', 'cart_id']),
];
foreach($data['items'] as $item) {
$finalData['items'][] = $this->prepareDataForOrderItem($item);
}
return $finalData;
}
/**
* Prepares data for order item
*
* @return array
*/
public function prepareDataForOrderItem($data)
{
$finalData = [
'product' => $this->product->find($data['product_id']),
'sku' => $data['sku'],
'type' => $data['type'],
'name' => $data['name'],
'weight' => $data['weight'],
'total_weight' => $data['total_weight'],
'qty_ordered' => $data['quantity'],
'price' => $data['price'],
'base_price' => $data['base_price'],
'total' => $data['total'],
'base_total' => $data['base_total'],
'additional' => $data['additional'],
];
if(isset($data['child']) && $data['child']) {
$finalData['child'] = $this->prepareDataForOrderItem($data['child']);
}
return $finalData;
}
}

View File

@ -15,10 +15,11 @@ class CreateCartTable extends Migration
{
Schema::create('cart', function (Blueprint $table) {
$table->increments('id');
$table->integer('customer_id')->unsigned()->nullable();
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->integer('channel_id')->unsigned();
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
$table->string('customer_email')->nullable();
$table->string('customer_first_name')->nullable();
$table->string('customer_last_name')->nullable();
$table->string('shipping_method')->nullable();
$table->string('coupon_code')->nullable();
$table->boolean('is_gift')->default(0);
@ -27,8 +28,8 @@ class CreateCartTable extends Migration
$table->decimal('exchange_rate', 12, 4)->nullable();
$table->string('global_currency_code')->nullable();
$table->string('base_currency_code')->nullable();
$table->string('store_currency_code')->nullable();
$table->string('quote_currency_code')->nullable();
$table->string('channel_currency_code')->nullable();
$table->string('cart_currency_code')->nullable();
$table->decimal('grand_total', 12, 4)->default(0)->nullable();
$table->decimal('base_grand_total', 12, 4)->default(0)->nullable();
$table->decimal('sub_total', 12, 4)->default(0)->nullable();
@ -37,9 +38,16 @@ class CreateCartTable extends Migration
$table->decimal('base_sub_total_with_discount', 12, 4)->default(0)->nullable();
$table->string('checkout_method')->nullable();
$table->boolean('is_guest')->nullable();
$table->boolean('is_active')->nullable()->default(0);
$table->string('customer_full_name')->nullable();
$table->boolean('is_active')->nullable()->default(1);
$table->string('customer_first_name')->nullable();
$table->string('customer_last_name')->nullable();
$table->string('customer_email')->nullable();
$table->dateTime('conversion_time')->nullable();
$table->integer('customer_id')->unsigned()->nullable();
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->integer('channel_id')->unsigned();
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
$table->timestamps();
});
}

View File

@ -44,53 +44,6 @@ class CartComposer
}
public function compose(View $view) {
// session()->forget('cart');
// return redirect()->back();
if(auth()->guard('customer')->check()) {
$cart = $this->cart->findOneByField('customer_id', auth()->guard('customer')->user()->id);
if(isset($cart)) {
$cartItems = $this->cart->items($cart['id']);
$products = array();
foreach($cartItems as $cartItem) {
$image = $this->productImage->getGalleryImages($cartItem->product);
if(isset($image[0]['small_image_url'])) {
$products[$cartItem->product->id] = [$cartItem->product->name, $cartItem->price, $image[0]['small_image_url'], $cartItem->quantity];
}
else {
$products[$cartItem->product->id] = [$cartItem->product->name, $cartItem->price, 'null', $cartItem->quantity];
}
}
session()->put('cart', $cart);
$view->with('cart', $products);
}
} else {
if($cart = session()->get('cart')) {
if(isset($cart)) {
$cartItems = $this->cart->items($cart['id']);
$products = array();
foreach($cartItems as $cartItem) {
$image = $this->productImage->getGalleryImages($cartItem->product);
if(isset($image[0]['small_image_url'])) {
$products[$cartItem->product->id] = [$cartItem->product->name, $cartItem->price, $image[0]['small_image_url'], $cartItem->quantity];
}
else {
$products[$cartItem->product->id] = [$cartItem->product->name, $cartItem->price, 'null', $cartItem->quantity];
}
}
$view->with('cart', $products);
}
}
}
}
}

View File

@ -1,10 +1,10 @@
<?php
use Webkul\Checkout\Cart;
if (! function_exists('cart')) {
function cart()
{
return new Cart;
return app()->make(Cart::class);
}
}
?>

View File

@ -13,10 +13,12 @@ class Cart extends Model
{
protected $table = 'cart';
protected $fillable = ['customer_id', 'session_id', 'channel_id', 'coupon_code', 'is_gift', 'items_count', 'items_qty', 'exchange_rate', 'global_currency_code', 'base_currency_code', 'store_currency_code', 'quote_currency_code', 'grand_total', 'base_grand_total', 'sub_total', 'base_sub_total', 'sub_total_with_discount', 'base_sub_total_with_discount', 'checkout_method', 'is_guest', 'is_active', 'customer_full_name', 'conversion_time'];
protected $fillable = ['customer_id', 'session_id', 'channel_id', 'coupon_code', 'is_gift', 'items_count', 'items_qty', 'exchange_rate', 'global_currency_code', 'base_currency_code', 'channel_currency_code', 'cart_currency_code', 'grand_total', 'base_grand_total', 'sub_total', 'base_sub_total', 'sub_total_with_discount', 'base_sub_total_with_discount', 'checkout_method', 'is_guest', 'is_active', 'customer_first_name', 'conversion_time'];
protected $hidden = ['coupon_code'];
protected $with = ['items', 'items.child', 'shipping_address', 'billing_address', 'selected_shipping_rate', 'payment'];
public function items() {
return $this->hasMany(CartItem::class)->whereNull('parent_id');
}
@ -73,12 +75,20 @@ class Cart extends Model
return $this->hasManyThrough(CartShippingRate::class, CartAddress::class, 'cart_id', 'cart_address_id');
}
/**
* Get all of the attributes for the attribute groups.
*/
public function selected_shipping_rate()
{
return $this->shipping_rates()->where('method', $this->shipping_method);
}
/**
* Get all of the attributes for the attribute groups.
*/
public function getSelectedShippingRateAttribute()
{
return $this->shipping_rates()->where('method', $this->shipping_method)->first();
return $this->selected_shipping_rate()->where('method', $this->shipping_method)->first();
}
/**

View File

@ -23,8 +23,6 @@ class CheckoutServiceProvider extends ServiceProvider
$router->aliasMiddleware('admin', RedirectIfNotAdmin::class);
$router->aliasMiddleware('customer', RedirectIfNotCustomer::class);
$this->app->register(ComposerServiceProvider::class);
}
/**
@ -44,7 +42,6 @@ class CheckoutServiceProvider extends ServiceProvider
*/
protected function registerFacades()
{
//to make the cart facade and bind the
//alias to the class needed to be called.
$loader = AliasLoader::getInstance();

View File

@ -1,32 +0,0 @@
<?php
namespace Webkul\Checkout\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use View;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function boot()
{
//using the class based composers...
View::composer(['shop::layouts.header.index'], 'Webkul\Checkout\Http\ViewComposers\CartComposer');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}

View File

@ -65,16 +65,4 @@ class CartRepository extends Repository
return $this->model->destroy($cart_id);
}
/**
* Used to get items
* for cart explicitly,
* use cart instance
* instead.
*
* @return Mixed
*/
public function items($cartId) {
return $this->model->find($cartId)->items;
}
}

View File

@ -17,14 +17,17 @@ class CreateWishlistTable extends Migration
$table->increments('id');
$table->integer('channel_id')->unsigned();
$table->foreign('channel_id')->references('id')->on('channels');
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->integer('customer_id')->unsigned();
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->json('item_options')->nullable();
$table->date('moved_to_cart')->nullable();
$table->boolean('shared')->nullable();
$table->date('time_of_moving');
$table->date('time_of_moving')->nullable();
$table->timestamps();
});
}

View File

@ -5,6 +5,7 @@ namespace Webkul\Customer\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Webkul\Customer\Repositories\CustomerRepository;
use Webkul\Customer\Repositories\WishlistRepository;
use Auth;
/**
@ -18,44 +19,101 @@ use Auth;
*/
class WishlistController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
protected $_config;
protected $customer;
protected $wishlist;
public function __construct(CustomerRepository $customer)
/**
* Initializes the required repository instances.
*
* @param $customer
* @param $wishlist
*/
public function __construct(CustomerRepository $customer, WishlistRepository $wishlist)
{
$this->middleware('customer');
$this->_config = request('_config');
$this->customer = $customer;
$this->wishlist = $wishlist;
}
/**
* For taking the customer
* to the dashboard after
* authentication
* @return view
* Displays the listing resources if the customer having items in wishlist.
*/
private function getCustomer($id) {
$customer = collect($this->customer->findOneWhere(['id'=>$id]));
return $customer;
}
public function index() {
$id = auth()->guard('customer')->user()->id;
$wishlists = $this->wishlist->findWhere(['channel_id' => core()->getCurrentChannel()->id,'customer_id' => auth()->guard('customer')->user()->id]);
$customer = $this->getCustomer($id);
$wishlistItems = array();
return view($this->_config['view'])->with('customer', $customer);
foreach($wishlists as $wishlist) {
array_push($wishlistItems, $this->wishlist->getItemsWithProducts($wishlist->id));
}
return view($this->_config['view'])->with('items', $wishlistItems);
}
public function wishlist() {
return view($this->_config['view']);
/**
* Function to add item to the wishlist.
*
* @param integer $itemId
*/
public function add($itemId) {
$data = [
'channel_id' => core()->getCurrentChannel()->id,
'product_id' => $itemId,
'customer_id' => auth()->guard('customer')->user()->id
];
$checked = $this->wishlist->findWhere(['channel_id' => core()->getCurrentChannel()->id, 'product_id' => $itemId, 'customer_id' => auth()->guard('customer')->user()->id]);
if($checked->isEmpty()) {
if($this->wishlist->create($data)) {
session()->flash('success', trans('customer::app.wishlist.success'));
return redirect()->back();
} else {
session()->flash('error', trans('customer::app.wishlist.failure'));
return redirect()->back();
}
} else {
session()->flash('warning', trans('customer::app.wishlist.already'));
return redirect()->back();
}
}
/**
* Function to remove item to the wishlist.
*
* @param integer $itemId
*/
public function remove($itemId) {
if($this->wishlist->deleteWhere(['customer_id' => auth()->guard('customer')->user()->id, 'channel_id' => core()->getCurrentChannel()->id, 'product_id' => $itemId])) {
session()->flash('success', trans('customer::app.wishlist.remove'));
return redirect()->back();
} else {
session()->flash('error', trans('customer::app.wishlist.remove-fail'));
return redirect()->back();
}
}
/**
* Function to move item from wishlist to cart.
*
* @param integer $itemId
*/
public function moveToCart() {
dd('adding item to wishlist');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Webkul\Customer\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Product\Models\Product;
class Wishlist extends Model
{
protected $table = 'wishlist';
protected $fillable = ['channel_id', 'product_id', 'customer_id', 'item_options','moved_to_cart','shared','time_of_moving'];
public function item_wishlist() {
return $this->belongsTo(Product::class, 'product_id');
}
}

View File

@ -15,6 +15,8 @@ class CustomerServiceProvider extends ServiceProvider
{
$router->aliasMiddleware('customer', RedirectIfNotCustomer::class);
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'customer');
$this->loadMigrationsFrom(__DIR__ . '/../Database/migrations');
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'customer');

View File

@ -0,0 +1,64 @@
<?php
namespace Webkul\Customer\Repositories;
use Webkul\Core\Eloquent\Repository;
/**
* Wishlist Reposotory
*
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class WishlistRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Customer\Models\Wishlist';
}
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
$wishlist = $this->model->create($data);
return $wishlist;
}
/**
* @param array $data
* @param $id
* @param string $attribute
* @return mixed
*/
public function update(array $data, $id, $attribute = "id")
{
$wishlist = $this->find($id);
$wishlist->update($data);
return $wishlist;
}
/**
* To retrieve products with wishlist m
* for a listing resource.
*
* @param integer $id
*/
public function getItemsWithProducts($id) {
return $this->model->find($id)->item_wishlist;
}
}

View File

@ -0,0 +1,12 @@
<?php
return [
'wishlist' => [
'success' => 'Item Successfully Added To Wishlist',
'failure' => 'Item Cannot Be Added To Wishlist',
'already' => 'Item Already Present In Your Wishlist',
'removed' => 'Item Successfully Added To Wishlist',
'remove-fail' => 'Item Cannot Be Removed From Wishlist',
'empty' => 'You Don\'t Have Any Items In Your Wishlist'
],
];

View File

@ -141,15 +141,36 @@ class Product extends Model
*/
public function isSaleable()
{
if($this->status) {
if($this->inventories->sum('qty')) {
return true;
}
}
if(!$this->status)
return false;
if($this->haveSufficientQuantity(1))
return true;
return false;
}
/**
* @param integer $qty
*
* @return bool
*/
public function haveSufficientQuantity($qty)
{
$inventories = $this->inventory_sources()->orderBy('priority', 'asc')->get();
$total = 0;
foreach($inventories as $inventorySource) {
if(!$inventorySource->status)
continue;
$total += $inventorySource->pivot->qty;
}
return $qty <= $total ? true : false;
}
/**
* Get an attribute from the model.
*

View File

@ -395,7 +395,7 @@ class ProductRepository extends Repository
]));
$params = request()->input();
return $this->scopeQuery(function($query){
return $query->distinct()->addSelect('products.*');
})->paginate(isset($params['limit']) ? $params['limit'] : 9, ['products.id']);

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Sales\Contracts;
interface OrderItemInventory
{
}

View File

@ -16,6 +16,7 @@ class CreateOrdersTable extends Migration
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->string('increment_id');
$table->string('status')->nullable();
$table->boolean('is_guest')->nullable();
$table->string('customer_email')->nullable();

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateOrderItemInventories extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('order_item_inventories', function (Blueprint $table) {
$table->increments('id');
$table->integer('qty')->default(0);
$table->integer('inventory_source_id')->unsigned()->nullable();
$table->integer('order_item_id')->unsigned()->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('order_item_inventories');
}
}

View File

@ -7,13 +7,13 @@ use Webkul\Sales\Contracts\Order as OrderContract;
class Order extends Model implements OrderContract
{
protected $guarded = ['id', 'created_at', 'updated_at'];
protected $guarded = ['id', 'items', 'shipping_address', 'billing_address', 'payment', 'created_at', 'updated_at'];
/**
* Get the order items record associated with the order.
*/
public function items() {
return $this->hasMany(CartItemProxy::modelClass())->whereNull('parent_id');
return $this->hasMany(OrderItemProxy::modelClass())->whereNull('parent_id');
}
/**

View File

@ -10,6 +10,8 @@ class OrderAddress extends Model implements OrderAddressContract
{
protected $table = 'order_address';
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Get of the customer fullname.
*/

View File

@ -7,6 +7,8 @@ use Webkul\Sales\Contracts\OrderItem as OrderItemContract;
class OrderItem extends Model implements OrderItemContract
{
protected $guarded = ['id', 'child', 'created_at', 'updated_at'];
/**
* Get the order record associated with the order item.
*/
@ -30,4 +32,11 @@ class OrderItem extends Model implements OrderItemContract
{
return $this->belongsTo(OrderItemProxy::modelClass(), 'parent_id');
}
/**
* Get the inventories record associated with the order item.
*/
public function inventories() {
return $this->hasMany(CartItemInventoyrProxy::modelClass());
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\Sales\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Sales\Contracts\OrderItemInventory as OrderItemInventoryContract;
class OrderItemInventory extends Model implements OrderItemInventoryContract
{
protected $guarded = ['id', 'child', 'created_at', 'updated_at'];
/**
* Get the order item record associated with the order item inventory.
*/
public function order_item()
{
return $this->belongsTo(OrderItemProxy::modelClass());
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Sales\Models;
use Konekt\Concord\Proxies\ModelProxy;
class OrderItemInventoryProxy extends ModelProxy
{
}

View File

@ -9,4 +9,6 @@ use Webkul\Sales\Contracts\OrderPayment as OrderPaymentContract;
class OrderPayment extends Model implements OrderPaymentContract
{
protected $table = 'order_payment';
protected $guarded = ['id', 'created_at', 'updated_at'];
}

View File

@ -9,6 +9,7 @@ class ModuleServiceProvider extends BaseModuleServiceProvider
protected $models = [
\Webkul\Sales\Models\Order::class,
\Webkul\Sales\Models\OrderItem::class,
\Webkul\Sales\Models\OrderItemInventory::class,
\Webkul\Sales\Models\OrderAddress::class,
\Webkul\Sales\Models\OrderPayment::class,
\Webkul\Sales\Models\Invoice::class,

View File

@ -0,0 +1,78 @@
<?php
namespace Webkul\Sales\Repositories;
use Illuminate\Container\Container as App;
use Webkul\Core\Eloquent\Repository;
/**
* Order Item Inventory Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class OrderItemInventoryRepository extends Repository
{
/**
* Specify Model class name
*
* @return Mixed
*/
function model()
{
return 'Webkul\Sales\Contracts\OrderItemInventory';
}
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
$orderItem = $data['orderItem'];
$orderedQuantity = $orderItem->qty_ordered;
$product = $orderItem->type == 'configurable' ? $orderItem->child->product : $orderItem->product;
if($product) {
$inventories = $product->inventory_sources()->orderBy('priority', 'asc')->get();
foreach($inventories as $inventorySource) {
if(!$orderedQuantity)
break;
$sourceQuantity = $inventorySource->pivot->qty;
if(!$inventorySource->status || !$sourceQuantity)
continue;
if($sourceQuantity >= $orderedQuantity) {
$orderItemQuantity = $orderedQuantity;
$sourceQuantity -= $orderItemQuantity;
$orderedQuantity = 0;
} else {
$orderItemQuantity = $sourceQuantity;
$sourceQuantity = 0;
$orderedQuantity -= $orderItemQuantity;
}
$this->model->create([
'qty' => $orderItemQuantity,
'order_item_id' => $orderItem->id,
'inventory_source_id' => $inventorySource->id,
]);
$inventorySource->pivot->update([
'qty' => $sourceQuantity
]);
}
}
}
}

View File

@ -24,4 +24,20 @@ class OrderItemRepository extends Repository
{
return 'Webkul\Sales\Contracts\OrderItem';
}
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
if(isset($data['product']) && $data['product']) {
$data['product_id'] = $data['product']->id;
$data['product_type'] = get_class($data['product']);
unset($data['product']);
}
return $this->model->create($data);
}
}

View File

@ -3,9 +3,12 @@
namespace Webkul\Sales\Repositories;
use Illuminate\Container\Container as App;
use Webkul\Core\Eloquent\Repository;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Model;
use Webkul\Core\Eloquent\Repository;
use Webkul\Sales\Repositories\OrderItemRepository;
use Webkul\Sales\Repositories\OrderItemInventoryRepository;
/**
* Order Reposotory
@ -23,19 +26,30 @@ class OrderRepository extends Repository
*/
protected $orderItem;
/**
* OrderItemInventoryRepository object
*
* @var Object
*/
protected $orderItemInventory;
/**
* Create a new repository instance.
*
* @param Webkul\Sales\Repositories\OrderItemRepository $orderItem
* @param Webkul\Sales\Repositories\OrderItemRepository $orderItem
* @param Webkul\Sales\Repositories\OrderItemInventoryRepository $orderItemInventory
* @return void
*/
public function __construct(
OrderItemRepository $orderItem,
OrderItemInventoryRepository $orderItemInventory,
App $app
)
{
$this->orderItem = $orderItem;
$this->orderItemInventory = $orderItemInventory;
parent::__construct($app);
}
@ -56,15 +70,37 @@ class OrderRepository extends Repository
*/
public function create(array $data)
{
$this->validateOrder();
DB::beginTransaction();
try {
Event::fire('checkout.order.save.before', $data);
$order = null;
if(isset($data['customer']) && $data['customer'] instanceof Model) {
$data['customer_id'] = $data['customer']->id;
$data['customer_type'] = get_class($data['customer']);
} else {
unset($data['customer']);
}
$data['status'] = core()->getConfigData('paymentmethods.' . $data['payment']['method'] . '.status') ?? 'pending';
$order = $this->model->create(array_merge($data, ['increment_id' => $this->generateIncrementId()]));
$order->payment()->create($data['payment']);
$order->addresses()->create($data['shipping_address']);
$order->addresses()->create($data['billing_address']);
foreach($data['items'] as $item) {
$orderItem = $this->orderItem->create(array_merge($item, ['order_id' => $order->id]));
if(isset($item['child']) && $item['child']) {
$orderItem->child = $this->orderItem->create(array_merge($item['child'], ['order_id' => $order->id, 'parent_id' => $orderItem->id]));
}
$this->orderItemInventory->create(['orderItem' => $orderItem]);
}
} catch (\Exception $e) {
DB::rollBack();
@ -77,4 +113,16 @@ class OrderRepository extends Repository
return $order;
}
/**
* @inheritDoc
*/
public function generateIncrementId()
{
$lastOrder = $this->model->orderBy('id', 'desc')->limit(1)->first();
$lastId = $lastOrder ? $lastOrder->id : 0;
return $lastId + 1;
}
}

View File

@ -122,7 +122,6 @@ class CartController extends Controller
$data = request()->except('_token');
foreach($data['qty'] as $id => $quantity) {
// dd($id, $quantity);
if($quantity <= 0) {
session()->flash('warning', trans('shop::app.checkout.cart.quantity.illegal'));
@ -135,5 +134,6 @@ class CartController extends Controller
}
public function test() {
$result = Cart::isConfigurable(9);
}
}

View File

@ -53,10 +53,10 @@ class OnepageController extends Controller
*/
public function index()
{
if(!$cart = Cart::getCart())
if(Cart::hasError())
return redirect()->route('shop.checkout.cart.index');
return view($this->_config['view'])->with('cart', $cart);
return view($this->_config['view'])->with('cart', Cart::getCart());
}
/**
@ -67,7 +67,7 @@ class OnepageController extends Controller
*/
public function saveAddress(CustomerAddressForm $request)
{
if(!Cart::saveCustomerAddress(request()->all()) || !$rates = Shipping::collectRates())
if(Cart::hasError() || !Cart::saveCustomerAddress(request()->all()) || !$rates = Shipping::collectRates())
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
return response()->json($rates);
@ -82,7 +82,7 @@ class OnepageController extends Controller
{
$shippingMethod = request()->get('shipping_method');
if(!$shippingMethod || !Cart::saveShippingMethod($shippingMethod))
if(Cart::hasError() || !$shippingMethod || !Cart::saveShippingMethod($shippingMethod))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
Cart::collectTotals();
@ -99,7 +99,7 @@ class OnepageController extends Controller
{
$payment = request()->get('payment');
if(!$payment || !Cart::savePaymentMethod($payment))
if(Cart::hasError() || !$payment || !Cart::savePaymentMethod($payment))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
$cart = Cart::getCart();
@ -117,11 +117,16 @@ class OnepageController extends Controller
*/
public function saveOrder()
{
if(Cart::hasError())
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
Cart::collectTotals();
$this->validateOrder();
$order = $this->orderRepository->create([]);
$order = $this->orderRepository->create(Cart::prepareDataForOrder());
Cart::deActivateCart();
session()->flash('order', $order);
@ -150,5 +155,22 @@ class OnepageController extends Controller
*/
public function validateOrder()
{
$cart = Cart::getCart();
if(!$cart->shipping_address) {
throw new \Exception(trans('Please check shipping address.'));
}
if(!$cart->billing_address) {
throw new \Exception(trans('Please check billing address.'));
}
if(!$cart->selected_shipping_rate) {
throw new \Exception(trans('Please specify shipping method.'));
}
if(!$cart->payment) {
throw new \Exception(trans('Please specify payment method.'));
}
}
}

View File

@ -10,10 +10,23 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'shop::products.index'
]);
Route::get('/checkout/cart', 'Webkul\Shop\Http\Controllers\CartController@index')->defaults('_config', [
//checkout and cart
Route::get('checkout/cart', 'Webkul\Shop\Http\Controllers\CartController@index')->defaults('_config', [
'view' => 'shop::checkout.cart.index'
])->name('shop.checkout.cart.index');
Route::post('checkout/cart/add/{id}', 'Webkul\Shop\Http\Controllers\CartController@add')->name('cart.add');
Route::get('checkout/cart/remove/{id}', 'Webkul\Shop\Http\Controllers\CartController@remove')->name('cart.remove');
Route::post('/checkout/cart', 'Webkul\Shop\Http\Controllers\CartController@updateBeforeCheckout')->defaults('_config',[
'redirect' => 'shop.checkout.cart.index'
])->name('shop.checkout.cart.update');
Route::get('/checkout/cart/remove/{id}', 'Webkul\Shop\Http\Controllers\CartController@remove')->defaults('_config',[
'redirect' => 'shop.checkout.cart.index'
])->name('shop.checkout.cart.remove');
Route::get('/checkout/onepage', 'Webkul\Shop\Http\Controllers\OnepageController@index')->defaults('_config', [
'view' => 'shop::checkout.onepage'
])->name('shop.checkout.onepage.index');
@ -30,10 +43,6 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'shop::checkout.success'
])->name('shop.checkout.success');
Route::get('test', 'Webkul\Shop\Http\Controllers\CartController@test');
Route::get('mtest', 'Webkul\Shop\Http\Controllers\CartController@mergeTest');
//dummy
Route::get('test', 'Webkul\Shop\Http\Controllers\CartController@test');
@ -41,18 +50,6 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'shop::products.view'
])->name('shop.products.index');
Route::post('product/cart/add/{id}', 'Webkul\Shop\Http\Controllers\CartController@add')->name('cart.add');
Route::get('product/cart/remove/{id}', 'Webkul\Shop\Http\Controllers\CartController@remove')->name('cart.remove');
Route::post('/checkout/cart', 'Webkul\Shop\Http\Controllers\CartController@updateBeforeCheckout')->defaults('_config',[
'redirect' => 'shop.checkout.cart.index'
])->name('shop.checkout.cart.update');
Route::get('/checkout/cart/remove/{id}', 'Webkul\Shop\Http\Controllers\CartController@remove')->defaults('_config',[
'redirect' => 'shop.checkout.cart.index'
])->name('shop.checkout.cart.remove');
//Routes for product cart ends
// Product Review routes
Route::get('/reviews/{slug}', 'Webkul\Shop\Http\Controllers\ReviewController@show')->defaults('_config', [
@ -101,6 +98,11 @@ Route::group(['middleware' => ['web']], function () {
'redirect' => 'customer.session.index'
])->name('customer.session.destroy');
//wishlist
Route::get('wishlist/add/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@add')->name('customer.wishlist.add');
Route::get('wishlist/remove/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@remove')->name('customer.wishlist.remove');
//customer account
Route::prefix('account')->group(function () {
@ -122,12 +124,9 @@ Route::group(['middleware' => ['web']], function () {
Route::post('profile/edit', 'Webkul\Customer\Http\Controllers\CustomerController@edit')->defaults('_config', [
'view' => 'shop::customers.account.profile.edit'
])->name('customer.profile.edit');
/* Profile Routes Ends Here */
/* Routes for Addresses */
Route::get('address/index', 'Webkul\Customer\Http\Controllers\AddressController@index')->defaults('_config', [
'view' => 'shop::customers.account.address.address'
])->name('customer.address.index');
@ -152,7 +151,7 @@ Route::group(['middleware' => ['web']], function () {
/* Routes for Addresses ends here */
/* Wishlist route */
Route::get('wishlist', 'Webkul\Customer\Http\Controllers\WishlistController@wishlist')->defaults('_config', [
Route::get('wishlist', 'Webkul\Customer\Http\Controllers\WishlistController@index')->defaults('_config', [
'view' => 'shop::customers.account.wishlist.wishlist'
])->name('customer.wishlist.index');
@ -165,7 +164,6 @@ Route::group(['middleware' => ['web']], function () {
Route::get('reviews', 'Webkul\Customer\Http\Controllers\CustomerController@reviews')->defaults('_config', [
'view' => 'shop::customers.account.reviews.reviews'
])->name('customer.reviews.index');
});
});
});

View File

@ -5,6 +5,7 @@ namespace Webkul\Shop\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Webkul\Product\Product\ProductImage;
use View;
class ComposerServiceProvider extends ServiceProvider

View File

@ -1,7 +1,16 @@
<template>
<li>
<a :href="this.item['translations'][0].slug">{{ this.item['translations'][0].name }}&emsp;<i class="icon dropdown-right-icon"
v-if="haveChildren && item.parent_id != null"></i></a>
<div class="name">
<a :href="this.item['translations'][0].slug">{{ this.item['translations'][0].name }}&emsp;<i class="icon dropdown-right-icon"
v-if="haveChildren && item.parent_id != null"></i></a>
</div>
<div class="click" v-if="haveChildren">
<i class="icon dropdown-right-icon"></i>
</div>
<ul v-if="haveChildren">
<category-item
v-for="(child, index) in item.children"

View File

@ -1,6 +1,15 @@
<template>
<li>
<a :href="this.item['translations'][0].slug">{{ this.item['translations'][0].name }}&emsp;<i class="icon dropdown-right-icon"
v-if="haveChildren && item.parent_id != null"></i></a>
<ul v-if="haveChildren" id="child">
<category-item
v-for="(child, index) in item.children"
:key="index"
:item="child">
</category-item>
</ul>
</li>
</template>
<script>
@ -17,7 +26,6 @@ export default {
},
computed: {
haveChildren() {
console.log(this.item.name);
return this.item.children.length ? true : false;
}
}

View File

@ -1998,4 +1998,3 @@ section.review {
}
}
// customer section css end here

View File

@ -91,15 +91,56 @@
white-space: nowrap;
}
.product-card.wishlist-icon {
cursor: pointer;
}
}
//wishlist icon hover properties
.add-to-wishlist {
.wishlist-icon {
&:hover {
background-image: url('../images/wishadd.svg');
}
}
}
//wishlist-icon-hover
.product-card.wishlist-icon:hover {
background-image: url('../images/wishadd.svg');
//wishlist item
.wishlist-item {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
height: 125px;
.media-info {
display: flex;
flex-direction: row;
.media {
height: 125px;
width: 100px;
}
.info {
display: block;
margin-left: 20px;
}
}
.operations {
height: 120px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
a {
width: 100%;
span {
float: right;
}
}
}
}
//product page price styles
@ -124,3 +165,9 @@
}
}
//horizontal rule
.horizontal-rule {
width: 100%;
height: 1px;
background: $border-color;
}

View File

@ -1,10 +1,6 @@
<?php
return [
'common' => [
'error' => 'Something went wrong, please contact us or try again later.'
],
'customer' => [
'signup-text' => [
'account_exists' => 'Already have an account',
@ -62,24 +58,39 @@ return [
'choose-option' => 'Choose an option'
],
'wishlist' => [
'title' => 'Wishlist',
'deleteall' => 'Delete All',
'moveall' => 'Move All Products To Cart'
],
'checkout' => [
'cart' => [
'integrity' => [
'missing_fields' =>'Cart System Integrity Violation, Some Required Fields Missing',
'missing_options' =>'Cart System Integrity Violation, Configurable product\'s options are missing',
],
'title' => 'Shopping Cart',
'empty' => 'Shopping Cart Is Empty',
'continue-shopping' => 'Continue Shopping',
'proceed-to-checkout' => 'Proceed To Checkout',
'quantity' => 'Quantity',
'remove' => 'Remove',
'remove-link' => 'Remove',
'move-to-wishlist' => 'Move to Wishlist',
'quantity' => [
'quantity' => 'Quantity',
'illegal' => 'Quantity cannot be lesser than one.'
'success' => 'Quantity successfully updated',
'illegal' => 'Quantity cannot be lesser than one',
'inventory_warning' => 'The requested quantity is not available, please try again later'
],
'remove' => [
'cannot' => 'No items to remove from the cart',
'success' => 'Item successfully removed from the cart',
'error' => 'Cannot remove item from cart'
]
'item' => [
'error_remove' => 'No items to remove from the cart',
'success' => 'Item successfully added to cart',
'success_remove' => 'Item removed successfully',
'error_add' => 'Item cannot be added to cart',
],
'quantity-error' => 'Requested quantity is not available.'
],
'onepage' => [
@ -117,9 +128,17 @@ return [
'total' => [
'order-summary' => 'Order Summary',
'sub-total' => 'Sub Total',
'sub-total' => 'Items',
'grand-total' => 'Grand Total',
'delivery-charges' => 'Delivery Charges'
'delivery-charges' => 'Delivery Charges',
'price' => 'price'
],
'success' => [
'title' => 'Order successfully placed',
'thanks' => 'Thank you for your order!',
'order-id-info' => 'Your order id is #:order_id',
'info' => 'We will email you, your order details and tracking information.'
]
]
];

View File

@ -48,31 +48,29 @@
@if ($product->type == 'configurable')
<div class="summary">
{{-- @foreach (cart::getItemAttributeOptionDetails($item) as $key => $option)
{{ Cart::getItemAttributeOptionDetails($item)['html'] }}
@endforeach --}}
</div>
@endif
<div class="misc">
<div class="qty-text" :class="[errors.has('qty') ? 'has-error' : '']">{{ __('shop::app.checkout.cart.quantity.quantity') }}</div>
{{-- <div class="box">{{ $item->quantity }}</div> --}}
<input class="box" type="text" v-validate="'required|numeric|min_value:1'" name="qty[{{$item->id}}]" value="{{ $item->quantity }}">
<span class="control-error" v-if="errors.has('qty[{{$item->id}}]')">@{{ errors.first('qty') }}</span>
{{-- @if($product->type == 'configurable')
<span class="remove"><a href="{{ route('shop.checkout.cart.remove', $item->child->id) }}">{{ __('shop::app.checkout.cart.remove') }}</a></span>
@else --}}
<span class="remove"><a href="{{ route('shop.checkout.cart.remove', $item->id) }}">{{ __('shop::app.checkout.cart.remove-link') }}</a></span>
<span class="remove"><a href="{{ route('shop.checkout.cart.remove', $item->id) }}">{{ __('shop::app.checkout.cart.remove') }}</a></span>
{{-- @endif --}}
<span class="towishlist">{{ __('shop::app.checkout.cart.move-to-wishlist') }}</span>
</div>
@if (!cart()->isItemHaveQuantity($item))
<div class="error-message">
{{ __('shop::app.checkout.cart.quantity-error') }}
</div>
@endif
</div>
</div>
@ -83,9 +81,12 @@
<div>
<input type="submit" class="btn btn-lg btn-primary" value="Update Cart" />
<a href="{{ route('shop.checkout.onepage.index') }}" class="btn btn-lg btn-primary">
{{ __('shop::app.checkout.cart.proceed-to-checkout') }}
</a>
@if (!cart()->hasError())
<a href="{{ route('shop.checkout.onepage.index') }}" class="btn btn-lg btn-primary">
{{ __('shop::app.checkout.cart.proceed-to-checkout') }}
</a>
@endif
</div>
</div>
</form>

View File

@ -5,9 +5,11 @@
<div class="form-header">
<h1>{{ __('shop::app.checkout.onepage.billing-address') }}</h1>
<a href="{{ route('customer.session.index') }}" class="btn btn-lg btn-primary">
{{ __('shop::app.checkout.onepage.sign-in') }}
</a>
@guest('customer')
<a href="{{ route('customer.session.index') }}" class="btn btn-lg btn-primary">
{{ __('shop::app.checkout.onepage.sign-in') }}
</a>
@endguest
</div>
<div class="control-group" :class="[errors.has('address-form.billing[first_name]') ? 'has-error' : '']">

View File

@ -1 +1,25 @@
{{ $order }}
@extends('shop::layouts.master')
@section('page_title')
{{ __('shop::app.checkout.success.title') }}
@stop
@section('content-wrapper')
<div class="order-success-content">
<h1>{{ __('shop::app.checkout.success.thanks') }}</h1>
<p>{{ __('shop::app.checkout.success.order-id-info', ['order_id' => $order->id]) }}</p>
<p>{{ __('shop::app.checkout.success.info') }}</p>
<div class="misc-controls">
<a href="{{ route('shop.home.index') }}" class="btn btn-lg btn-primary">
{{ __('shop::app.checkout.cart.continue-shopping') }}
</a>
</div>
</div>
@endsection

View File

@ -2,7 +2,15 @@
<h3>{{ __('shop::app.checkout.total.order-summary') }}</h3>
<div class="item-detail">
<label>{{ __('shop::app.checkout.total.sub-total') }}</label>
<label>
@if($cart->items_qty - intval($cart->items_qty) > 0)
{{ $cart->items_qty }}
@else
{{ intval($cart->items_qty) }}
@endif
{{ __('shop::app.checkout.total.sub-total') }}
{{ __('shop::app.checkout.total.price') }}
</label>
<label class="right">{{ core()->currency($cart->sub_total) }}</label>
</div>

View File

@ -1 +1,56 @@
<h1>Wishlist page here</h1>
@extends('shop::layouts.master')
@section('content-wrapper')
<div class="account-content">
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
@include('shop::customers.account.partials.sidemenu')
<div class="profile">
<div class="section-head">
<span class="profile-heading">{{ __('shop::app.wishlist.title') }}</span>
@if(count($items))
<div class="profile-edit">
<a href="" style="margin-right: 15px;">{{ __('shop::app.wishlist.deleteall') }}</a>
<a href="">{{ __('shop::app.wishlist.moveall') }}</a>
</div>
@endif
<div class="horizontal-rule"></div>
</div>
<div class="profile-content">
@if(count($items))
@foreach($items as $item)
<div class="wishlist-item mb-10">
<div class="media-info">
@php
$image = $productImageHelper->getProductBaseImage($item);
@endphp
<img class="media" src="{{ $image['small_image_url'] }}" />
<div class="info mt-20">
<div class="product-name">{{$item->name}}</div>
</div>
</div>
<div class="operations">
<a class="mb-50" href="{{ route('customer.wishlist.remove', $item->id) }}"><span class="icon trash-icon"></span></a>
<button class="btn btn-primary btn-md">Move To Cart</button>
</div>
</div>
<div class="horizontal-rule mb-10 mt-10"></div>
@endforeach
@else
<div class="empty">
{{ __('customer::app.wishlist.empty') }}
</div>
@endif
</div>
</div>
</div>
@endsection

View File

@ -69,7 +69,8 @@
<li><a href="{{ route('customer.wishlist.index') }}">Wishlist</a></li>
{{-- <li><a href="{{ route('customer.cart') }}">Cart</a></li> --}}
<li><a href="{{ route('shop.checkout.cart.index') }}">Cart</a></li>
<li><a href="{{ route('customer.orders.index') }}">Orders</a></li>
<li><a href="{{ route('customer.session.destroy') }}">Logout</a></li>
@ -83,57 +84,92 @@
</ul>
<ul class="cart-dropdown-container">
<?php $cart = cart()->getCart(); ?>
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
<li class="cart-dropdown">
<span class="icon cart-icon"></span>
@if(isset($cart))
@php
$cartInstance = session()->get('cart');
@endphp
<div class="dropdown-toggle">
@if($cart)
@php
$items = $cart->items;
@endphp
<div class="dropdown-toggle">
<div style="display: inline-block; cursor: pointer;">
@if($cart->items_qty - intval($cart->items_qty) > 0)
<span class="name"><span class="count"> {{ $cart->items_qty }} Products</span>
@else
<span class="name"><span class="count"> {{ intval($cart->items_qty) }} Products</span>
@endif
</div>
<i class="icon arrow-down-icon active"></i>
<div style="display: inline-block; cursor: pointer;">
<span class="name"><span class="count"> {{$cartInstance->items_count}} Products</span>
</div>
<i class="icon arrow-down-icon active"></i>
</div>
<div class="dropdown-list" style="display: none; top: 50px; right: 0px">
<div class="dropdown-container">
<div class="dropdown-cart">
<div class="dropdown-header">
<p class="heading">Cart Subtotal - {{ $cartInstance->sub_total }}</p>
</div>
<div class="dropdown-content">
@foreach($cart as $product)
<div class="item" >
<div class="item-image" >
<img src="{{$product['2']}}" />
</div>
<div class="item-details">
<div class="item-name">{{$product['0']}}</div>
<div class="item-price">{{$product['1']}}</div>
<div class="item-qty">Quantity - {{$product['3']}}</div>
</div>
<div class="dropdown-list" style="display: none; top: 50px; right: 0px">
<div class="dropdown-container">
<div class="dropdown-cart">
<div class="dropdown-header">
<p class="heading">Cart Subtotal - {{ $cart->sub_total }}</p>
</div>
@endforeach
</div>
<div class="dropdown-footer">
<a href="{{ route('shop.checkout.cart.index') }}">View Shopping Cart</a>
<button class="btn btn-primary btn-lg">CHECKOUT</button>
<div class="dropdown-content">
@foreach($items as $item)
@if($item->type == "configurable")
<div class="item">
<div class="item-image" >
@php
$images = $productImageHelper->getProductBaseImage($item->child->product);
@endphp
<img src="{{ $images['small_image_url'] }}" />
</div>
<div class="item-details">
<div class="item-name">{{ $item->child->name }}</div>
<div class="item-price">{{ $item->total }}</div>
<div class="item-qty">Quantity - {{ $item->quantity }}</div>
</div>
</div>
@else
<div class="item">
<div class="item-image" >
@php
$images = $productImageHelper->getProductBaseImage($item->product);
@endphp
<img src="{{ $images['small_image_url'] }}" />
</div>
<div class="item-details">
<div class="item-name">{{ $item->name }}</div>
<div class="item-price">{{ $item->total }}</div>
<div class="item-qty">Quantity - {{ $item->quantity }}</div>
</div>
</div>
@endif
@endforeach
</div>
<div class="dropdown-footer">
<a href="{{ route('shop.checkout.cart.index') }}">View Shopping Cart</a>
<button class="btn btn-primary btn-lg">CHECKOUT</button>
</div>
</div>
</div>
</div>
</div>
@else
<div class="dropdown-toggle">
<div style="display: inline-block; cursor: pointer;">
<span class="name"><span class="count"> 0 &nbsp;</span>Products</span>
<div class="dropdown-toggle">
<div style="display: inline-block; cursor: pointer;">
<span class="name"><span class="count"> 0 &nbsp;</span>Products</span>
</div>
</div>
</div>
@endif
</li>
</ul>
@ -147,17 +183,10 @@
<div class="dropdown-toggle">
<span class="icon account-icon"></span>
{{-- <div style="display: inline-block; cursor: pointer;">
<span class="name">Account</span>
</div>
<i class="icon arrow-down-icon active"></i> --}}
</div>
@guest
<div class="dropdown-list bottom-right" style="display: none;">
<div class="dropdown-container">
<label>Account</label>
@ -167,15 +196,15 @@
<li><a href="{{ route('customer.register.index') }}">Sign Up</a></li>
</ul>
</div>
</div>
@endguest
@auth('customer')
<div class="dropdown-list bottom-right" style="display: none;">
<div class="dropdown-container">
<label>Account</label>
<ul>
<li><a href="{{ route('customer.account.index') }}">Account</a></li>
@ -185,7 +214,8 @@
<li><a href="{{ route('customer.wishlist.index') }}">Wishlist</a></li>
{{-- <li><a href="{{ route('customer.cart') }}">Cart</a></li> --}}
<li><a href="{{ route('shop.checkout.cart.index') }}">Cart</a></li>
<li><a href="{{ route('customer.orders.index') }}">Orders</a></li>
<li><a href="{{ route('customer.session.destroy') }}">Logout</a></li>
@ -200,9 +230,9 @@
<ul class="resp-cart-dropdown-container">
<li class="cart-dropdown">
@if(isset($cart))
@if(isset($cart) && session()->has('cart'))
@php
$cartInstance = session()->get('cart');
$cart = session()->get('cart');
@endphp
<div class="dropdown-toggle">
<span class="icon cart-icon"></span>
@ -212,7 +242,7 @@
<div class="dropdown-container">
<div class="dropdown-cart">
<div class="dropdown-header">
<p class="heading">Cart Subtotal - {{ $cartInstance->sub_total }}</p>
<p class="heading">Cart Subtotal - {{ $cart->sub_total }}</p>
</div>
<div class="dropdown-content">
@ -240,7 +270,9 @@
@else
<div class="dropdown-toggle">
<div style="display: inline-block; cursor: pointer;">
<span class="name"><span class="count"> 0 &nbsp;</span>Products</span>
{{-- <span class="name"><span class="count"> 0 &nbsp;
</span>Products</span> --}}
<span class="icon cart-icon"></span>
</div>
</div>
@endif
@ -265,13 +297,8 @@
</div>
</div>
<div class="header-bottom" id="header-bottom">
@include('shop::layouts.header.nav-menu.navmenu')
</div>
<div class="responsive-nav">
<res-category-nav categories='@json($categories)' url="{{url()->to('/')}}"></res-category-nav>
</div>
</div>
@ -355,8 +382,27 @@
layerFilter.style.display ="none";
}
}
var click=document.getElementsByClassName('click');
var y=document.getElementById('child');
console.log(y);
for(let i=0 ; i <click.length ; i++){
click[i].addEventListener("click",function(){
});
}
}
</script>
@endpush
</div>

View File

@ -20,6 +20,7 @@
<body>
<div id="app">
<flash-wrapper ref='flashes'></flash-wrapper>
<div class="main-container-wrapper">

View File

@ -2,6 +2,6 @@
@include ('shop::products.add-to-cart', ['product' => $product])
<span class="product-card wishlist-icon"></span>
@include('shop::products.wishlist')
</div>

View File

@ -76,7 +76,6 @@
</div>
<div class="reponsive-sorter-limiter mb-20">
<div class="sorter">
@ -115,6 +114,4 @@
<div class="responsive-layred-filter mb-20">
<layered-navigation></layered-navigation>
</div>
</div>

View File

@ -1,4 +1 @@
<div class="icon share-icon">
<a href="#"></a>
</div>
<span class="icon share-icon"></span>

View File

@ -4,7 +4,6 @@
{{ $product->name }}
@stop
@section('content-wrapper')
<section class="product-detail">
<div class="category-breadcrumbs">
@ -36,8 +35,11 @@
</div>
<div class="quantity control-group" :class="[errors.has('quantity') ? 'has-error' : '']">
<label class="reqiured">Quantity</label>
<input name="quantity" class="control" value="1" v-validate="'required|numeric|min_value:1'" style="width: 60px;">
<span class="control-error" v-if="errors.has('quantity')">@{{ errors.first('quantity') }}</span>
</div>

View File

@ -49,7 +49,7 @@
template: '#product-options-template',
inject: ['$validator'],
inject: ['$validator'],
data: () => ({
config: @json($config),

View File

@ -1,5 +1,4 @@
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
<?php $images = $productImageHelper->getGalleryImages($product); ?>
<div class="product-image-group">
@ -32,10 +31,10 @@
<img :src="currentLargeImageUrl" id="pro-img"/>
<div class="icon whishlist-icon"> </div>
@include ('shop::products.sharelinks')
{{-- Uncomment the line below for activating share links --}}
{{-- @include('shop::products.sharelinks') --}}
@include('shop::products.wishlist')
</div>

View File

@ -0,0 +1,5 @@
@auth('customer')
<a class="add-to-wishlist" href="{{ route('customer.wishlist.add', $product->id) }}">
<span class="icon wishlist-icon"></span>
</a>
@endauth

View File

@ -178,12 +178,71 @@
white-space: nowrap;
}
.product-card .cart-fav-seg .product-card.wishlist-icon {
cursor: pointer;
.add-to-wishlist .wishlist-icon:hover {
background-image: url("../images/wishadd.svg");
}
.product-card.wishlist-icon:hover {
background-image: url("../images/wishadd.svg");
.wishlist-item {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 100%;
height: 125px;
}
.wishlist-item .media-info {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
}
.wishlist-item .media-info .media {
height: 125px;
width: 100px;
}
.wishlist-item .media-info .info {
display: block;
margin-left: 20px;
}
.wishlist-item .operations {
height: 120px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.wishlist-item .operations a {
width: 100%;
}
.wishlist-item .operations a span {
float: right;
}
.product-price {
@ -207,6 +266,12 @@
color: #FF6472;
}
.horizontal-rule {
width: 100%;
height: 1px;
background: #E8E8E8;
}
body {
margin: 0;
padding: 0;

View File

@ -30844,6 +30844,15 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
//
//
//
//
//
//
//
//
//
//
//
//
// define the item component
/* harmony default export */ __webpack_exports__["default"] = ({
@ -30873,13 +30882,21 @@ var render = function() {
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c("li", [
_c("a", { attrs: { href: this.item["translations"][0].slug } }, [
_vm._v(_vm._s(this.item["translations"][0].name) + ""),
_vm.haveChildren && _vm.item.parent_id != null
? _c("i", { staticClass: "icon dropdown-right-icon" })
: _vm._e()
_c("div", { staticClass: "name" }, [
_c("a", { attrs: { href: this.item["translations"][0].slug } }, [
_vm._v(_vm._s(this.item["translations"][0].name) + ""),
_vm.haveChildren && _vm.item.parent_id != null
? _c("i", { staticClass: "icon dropdown-right-icon" })
: _vm._e()
])
]),
_vm._v(" "),
_vm.haveChildren
? _c("div", { staticClass: "click" }, [
_c("i", { staticClass: "icon dropdown-right-icon" })
])
: _vm._e(),
_vm._v(" "),
_vm.haveChildren
? _c(
"ul",
@ -31937,6 +31954,15 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
//
//
//
//
//
//
//
//
//
//
//
//
// define the item component
/* harmony default export */ __webpack_exports__["default"] = ({
@ -31965,7 +31991,24 @@ var render = function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c("li")
return _c("li", [
_c("a", { attrs: { href: this.item["translations"][0].slug } }, [
_vm._v(_vm._s(this.item["translations"][0].name) + ""),
_vm.haveChildren && _vm.item.parent_id != null
? _c("i", { staticClass: "icon dropdown-right-icon" })
: _vm._e()
]),
_vm._v(" "),
_vm.haveChildren
? _c(
"ul",
{ attrs: { id: "child" } },
_vm._l(_vm.item.children, function(child, index) {
return _c("category-item", { key: index, attrs: { item: child } })
})
)
: _vm._e()
])
}
var staticRenderFns = []
render._withStripped = true