This commit is contained in:
prashant-webkul 2018-10-10 16:13:51 +05:30
commit d26758e49a
40 changed files with 1126 additions and 541 deletions

View File

@ -7,7 +7,7 @@
@section('content')
<div class="content">
<?php $locale = request()->get('locale') ?: app()->getLocale(); ?>
<?php $channel = request()->get('channel') ?: core()->getCurrentChannelCode(); ?>
<?php $channel = request()->get('channel') ?: core()->getDefaultChannelCode(); ?>
<form method="POST" action="" @submit.prevent="onSubmit" enctype="multipart/form-data">

View File

@ -31,10 +31,10 @@ class AttributeFamilyTableSeeder extends Seeder
'code' => 'url_key',
'position' => 3
], [
'code' => 'new_from',
'code' => 'new',
'position' => 4
], [
'code' => 'new_to',
'code' => 'featured',
'position' => 5
], [
'code' => 'visible_individually',

View File

@ -56,12 +56,12 @@ class AttributeTableSeeder extends Seeder
'is_configurable' => 0,
'is_user_defined' => 0
], [
'code' => 'new_from',
'admin_name' => 'New From',
'code' => 'new',
'admin_name' => 'New',
'en' => [
'name' => 'New From'
'name' => 'New'
],
'type' => 'datetime',
'type' => 'boolean',
'position' => 4,
'is_required' => 0,
'value_per_locale' => 0,
@ -70,12 +70,12 @@ class AttributeTableSeeder extends Seeder
'is_configurable' => 0,
'is_user_defined' => 0
], [
'code' => 'new_to',
'admin_name' => 'New To',
'code' => 'featured',
'admin_name' => 'Featured',
'en' => [
'name' => 'New To'
'name' => 'Featured'
],
'type' => 'datetime',
'type' => 'boolean',
'position' => 5,
'is_required' => 0,
'value_per_locale' => 0,

View File

@ -109,25 +109,11 @@ class Cart {
}
}
$child = $childData = null;
if($product->type == 'configurable') {
//Check if the product is salable
$child = $this->product->findOneByField('id', $data['selected_configurable_option']);
$parentData = [
'sku' => $product->sku,
'product_id' => $productId,
'quantity' => $data['quantity'],
'type' => 'configurable',
'name' => $product->name,
'price' => ($price = $child->price), //This should be price from the price helper
'base_price' => $price,
'total' => $price * $data['quantity'],
'base_total' => $price * $data['quantity'],
'weight' => ($weight = $child->weight),
'total_weight' => $weight * $data['quantity'],
'base_total_weight' => $weight * $data['quantity'],
];
//child row data
$childData = [
'product_id' => $data['selected_configurable_option'],
@ -136,33 +122,31 @@ class Cart {
'type' => $child->type,
'name' => $child->name
];
return ['parent' => $parentData, 'child' => $childData];
} else {
$parentData = [
'sku' => $product->sku,
'product_id' => $productId,
'quantity' => $data['quantity'],
'type' => 'simple',
'name' => $product->name,
'price' => $product->price,
'base_price' => $product->price,
'total' => $product->price * $data['quantity'],
'base_total' => $product->price * $data['quantity'],
'weight' => $product->weight,
'total_weight' => $product->weight * $data['quantity'],
'base_total_weight' => $product->weight * $data['quantity'],
];
return ['parent' => $parentData, 'child' => null];
}
$parentData = [
'sku' => $product->sku,
'product_id' => $productId,
'quantity' => $data['quantity'],
'type' => $product->type,
'name' => $product->name,
'price' => $price = ($product->type == 'configurable' ? $child->price : $product->price),
'base_price' => $price,
'total' => $price * $data['quantity'],
'base_total' => $price * $data['quantity'],
'weight' => $weight = ($product->type == 'configurable' ? $child->weight : $product->weight),
'total_weight' => $weight * $data['quantity'],
'base_total_weight' => $weight * $data['quantity']
];
return ['parent' => $parentData, 'child' => $childData];
}
/**
* Create new cart instance with the current item success.
*
* @param integer $id
* @param array $data
* @param array $data
*
* @return Response
*/
@ -175,72 +159,83 @@ class Cart {
//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_first_name'] = auth()->guard('customer')->user()->first_name;
$cartData['customer_last_name'] = auth()->guard('customer')->user()->last_name;
$cartData['customer_email'] = auth()->guard('customer')->user()->email;
} else {
$cartData['is_guest'] = 1;
}
$cartData['items_count'] = 1;
$cartData['items_qty'] = $data['quantity'];
if($cart = $this->cart->create($cartData)) {
$itemData['parent']['cart_id'] = $cart->id;
$product = $this->product->find($id);
if ($this->product->find($id)->type == "configurable") {
if ($product->type == "configurable") {
//parent item entry
$itemData['parent']['additional'] = json_encode($data);
if($parent = $this->cartItem->create($itemData['parent'])) {
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);
$this->putCart($cart);
session()->flash('success', trans('shop::app.checkout.cart.item.success'));
$this->collectTotals();
return redirect()->back();
return $cart;
}
}
} else if($this->product->find($id)->type != "configurable") {
if($result = $this->cartItem->create($itemData['parent'])) {
session()->put('cart', $cart);
} else if($product->type != "configurable") {
if($this->cartItem->create($itemData['parent'])) {
$this->putCart($cart);
session()->flash('success', trans('shop::app.checkout.cart.item.success'));
$this->collectTotals();
return redirect()->back();
return $cart;
}
}
}
session()->flash('error', trans('shop::app.checkout.cart.item.error_add'));
return redirect()->back();
return false;
}
/**
* Save cart
*
* @return mixed
*/
public function putCart($cart)
{
if(!auth()->guard('customer')->check()) {
session()->put('cart', $cart);
}
}
/**
* Returns cart
*
* @return Mixed
* @return mixed
*/
public function getCart()
{
$cart = null;
if(session()->has('cart')) {
$cart = $this->cart->find(session()->get('cart')->id);
} else if(auth()->guard('customer')->check()) {
if(auth()->guard('customer')->check()) {
$cart = $this->cart->findOneByField('customer_id', auth()->guard('customer')->user()->id);
} elseif(session()->has('cart')) {
$cart = $this->cart->find(session()->get('cart')->id);
}
return $cart && $cart->is_active ? $cart : null;
@ -276,38 +271,26 @@ class Cart {
*/
public function canAddOrUpdate($itemId, $quantity)
{
$item = $this->cartItem->findOneByField('id', $itemId);
$inventories = $item->product->inventories;
$inventory_sources = $item->product->inventory_sources;
$totalQty = 0;
foreach($inventory_sources as $inventory_source) {
if($inventory_source->status && $inventory_source->toArray()['pivot']['qty']) {
$totalQty = $totalQty + $inventory_source->toArray()['pivot']['qty'];
}
}
if ($quantity < 1) {
session()->flash('warning', trans('shop::app.checkout.cart.quantity.warning'));
return redirect()->back();
}
if($quantity <= $totalQty) {
$item = $this->cartItem->findOneByField('id', $itemId);
if($item->product->haveSufficientQuantity($quantity)) {
return true;
} else {
return false;
}
return false;
}
/**
* Add Items in a cart with some cart and item details.
*
* @param @id
* @param $data
* @param integer $id
* @param array $data
*
* @return void
*/
@ -315,14 +298,14 @@ class Cart {
{
$itemData = $this->prepareItemData($id, $data);
if(session()->has('cart')) {
$cart = $this->getCart();
if($cart = $this->getCart()) {
$product = $this->product->find($id);
$cartItems = $cart->items()->get();
$cartItems = $cart->items;
if(isset($cartItems)) {
if($cartItems->count()) {
foreach($cartItems as $cartItem) {
if($this->product->find($id)->type == "simple") {
if($product->type == "simple") {
if($cartItem->product_id == $id) {
$prevQty = $cartItem->quantity;
@ -348,7 +331,7 @@ class Cart {
return redirect()->back();
}
} else if($this->product->find($id)->type == "configurable") {
} else if($product->type == "configurable") {
if($cartItem->type == "configurable") {
$temp = $this->cartItem->findOneByField('parent_id', $cartItem->id);
if($temp->product_id == $data['selected_configurable_option']) {
@ -384,17 +367,13 @@ class Cart {
}
}
if($this->product->find($id)->type == "configurable") {
if($product->type == "configurable") {
$parent = $cart->items()->create($itemData['parent']);
$itemData['child']['parent_id'] = $parent->id;
// $this->canAddOrUpdate($parent->child->id, $parent->quantity);
$cart->items()->create($itemData['child']);
} else if($this->product->find($id)->type != "configurable"){
// $this->canAddOrUpdate($parent->id, $parent->quantity);
} else if($product->type != "configurable"){
$parent = $cart->items()->create($itemData['parent']);
}
@ -402,16 +381,16 @@ class Cart {
session()->flash('success', trans('shop::app.checkout.cart.item.success'));
return redirect()->back();
return $cart;
} else {
if(isset($cart)) {
$this->cart->delete($cart->id);
} else {
$this->createNewCart($id, $data);
return $this->createNewCart($id, $data);
}
}
} else {
$this->createNewCart($id, $data);
return $this->createNewCart($id, $data);
}
}
@ -421,9 +400,7 @@ class Cart {
*/
public function update($itemIds)
{
if(session()->has('cart')) {
$cart = $this->getCart();
if($cart = $this->getCart()) {
$items = $cart->items;
foreach($items as $item) {
@ -438,7 +415,7 @@ class Cart {
if($canBe == false) {
session()->flash('warning', trans('shop::app.checkout.cart.quantity.inventory_warning'));
return redirect()->back();
return $cart;
}
$item->update(['quantity' => $quantity]);
@ -447,10 +424,11 @@ class Cart {
}
}
}
session()->flash('success', trans('shop::app.checkout.cart.quantity.success'));
return redirect()->back();
session()->flash('success', trans('shop::app.checkout.cart.quantity.success'));
}
return $cart;
}
/**
@ -460,49 +438,18 @@ class Cart {
*/
public function removeItem($itemId)
{
if(session()->has('cart')) {
$cart = $this->getCart();
$items = $cart->items;
foreach($items as $item) {
if($item->id == $itemId) {
if($item->type == "configurable") {
$child = $item->child;
//delete the child first
$result = $this->cartItem->delete($child->id);
if($result)
$result = $this->cartItem->delete($item->id);
$this->collectTotals();
} else if($item->type == "simple" && $item->parent_id == null){
$result = $this->cartItem->delete($item->id);
$this->collectTotals();
}
}
}
$countItems = $this->cart->findOneByField('id', $cart->id)->items->count();
if($cart = $this->getCart()) {
$this->cartItem->delete($itemId);
//delete the cart instance if no items are there
if($countItems == 0) {
$result = $this->cart->delete($cart->id);
if($cart->items()->get()->count() == 0) {
$this->cart->delete($cart->id);
session()->forget('cart');
} else {
session()->forget('cart');
session()->put('cart', $this->cart->findOneByField('id', $cart->id));
}
if ($result) {
session()->flash('sucess', trans('shop::app.checkout.cart.quantity.success_remove'));
} else {
session()->flash('error', trans('shop::app.checkout.cart.quantity.error_remove'));
session()->flash('success', trans('shop::app.checkout.cart.quantity.success_remove'));
}
}
return redirect()->back();
}
/**
@ -678,7 +625,7 @@ class Cart {
if(session()->has('cart')) {
$cart = $this->cart->findOneByField('customer_id', auth()->guard('customer')->user()->id);
$guestCart = $this->getCart();
$guestCart = session()->get('cart');
if(!isset($cart)) {
$guestCart->update(['customer_id' => auth()->guard('customer')->user()->id, 'is_guest' => 0]);
@ -777,9 +724,6 @@ class Cart {
//forget the guest cart instance
session()->forget('cart');
//put the customer cart instance
session()->put('cart', $cart);
$this->collectTotals();
return redirect()->back();
@ -788,22 +732,6 @@ class Cart {
}
}
/**
* Destroys the session maintained for cart on customer logout.
*
* @return response
*/
public function destroyCart()
{
if(session()->has('cart')) {
session()->forget('cart');
return redirect()->back();
} else {
return redirect()->back();
}
}
/**
* Checks if cart has any error
*

View File

@ -48,7 +48,7 @@ class CreateCartItemsTable extends Migration
$table->json('additional')->nullable();
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->integer('cart_id')->unsigned();
$table->foreign('cart_id')->references('id')->on('cart')->onDelete('cascade');
$table->integer('tax_category_id')->unsigned()->nullable();
@ -57,7 +57,7 @@ class CreateCartItemsTable extends Migration
});
Schema::table('cart_items', function (Blueprint $table) {
$table->foreign('parent_id')->references('id')->on('cart_items');
$table->foreign('parent_id')->references('id')->on('cart_items')->onDelete('cascade');
});
}

View File

@ -29,7 +29,7 @@ class CreateCartAddress extends Migration
$table->integer('cart_id')->nullable()->unsigned();
$table->foreign('cart_id')->references('id')->on('cart')->onDelete('cascade');
$table->integer('customer_id')->nullable()->unsigned();
$table->foreign('customer_id')->references('id')->on('customers');
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->timestamps();
});
}

View File

@ -18,7 +18,7 @@ class CreateCartPayment extends Migration
$table->string('method');
$table->string('method_title')->nullable();
$table->integer('cart_id')->nullable()->unsigned();
$table->foreign('cart_id')->references('id')->on('cart');
$table->foreign('cart_id')->references('id')->on('cart')->onDelete('cascade');
$table->timestamps();
});
}

View File

@ -23,7 +23,7 @@ class CreateCartShippingRatesTable extends Migration
$table->double('price')->default(0)->nullable();
$table->double('base_price')->default(0)->nullable();
$table->integer('cart_address_id')->nullable()->unsigned();
$table->foreign('cart_address_id')->references('id')->on('cart_address');
$table->foreign('cart_address_id')->references('id')->on('cart_address')->onDelete('cascade');
$table->timestamps();
});
}

View File

@ -84,6 +84,34 @@ class Core
return ($channel = $this->getCurrentChannel()) ? $channelCode = $channel->code : '';
}
/**
* Returns default channel models
*
* @return mixed
*/
public function getDefaultChannel() {
static $channel;
if($channel)
return $channel;
return $channel = ChannelModel::first();
}
/**
* Returns default channel code
*
* @return string
*/
public function getDefaultChannelCode() {
static $channelCode;
if($channelCode)
return $channelCode;
return ($channel = $this->getDefaultChannel()) ? $channelCode = $channel->code : '';
}
/**
* Returns all locales
*

View File

@ -24,14 +24,6 @@ class TaxCategoryController extends Controller
*/
protected $_config;
/**
* Contains the current
* channel.
*
* @var string
*/
protected $currentChannelId;
/**
* Tax Rule Repository object
*
@ -49,8 +41,6 @@ class TaxCategoryController extends Controller
{
$this->middleware('admin');
$this->currentChannelId = core()->getCurrentChannel()->id;
$this->taxRule = $taxRule;
$this->taxRate = $taxRate;

View File

@ -47,7 +47,10 @@ class WishlistController extends Controller
* Displays the listing resources if the customer having items in wishlist.
*/
public function index() {
$wishlists = $this->wishlist->findWhere(['channel_id' => core()->getCurrentChannel()->id,'customer_id' => auth()->guard('customer')->user()->id]);
$wishlists = $this->wishlist->findWhere([
'channel_id' => core()->getCurrentChannel()->id,
'customer_id' => auth()->guard('customer')->user()->id]
);
$wishlistItems = array();

View File

@ -12,30 +12,14 @@ class CustomerEventsHandler {
public function onCustomerLogin($event)
{
/**
* handle the user login
* event to manage the
* after login, if
* the user has added any
* products as guest then
* the cart items from session
* will be transferred from
* cookie to the cart table
* in the database.
* handle the user login event to manage the after login, if the user has added any products as guest then
* the cart items from session will be transferred from cookie to the cart table in the database.
*
* Check whether cookie is
* present or not and then
* check emptiness and then
* do the appropriate actions.
* Check whether cookie is present or not and then check emptiness and then do the appropriate actions.
*/
Cart::mergeCart();
}
//Customer Logout Event Handler.
public function onCustomerLogout($event)
{
Cart::destroyCart();
}
/**
* Register the listeners for the subscriber.
*
@ -45,7 +29,5 @@ class CustomerEventsHandler {
public function subscribe($events)
{
$events->listen('customer.after.login', 'Webkul\Customer\Http\Listeners\CustomerEventsHandler@onCustomerLogin');
$events->listen('customer.after.logout', 'Webkul\Customer\Http\Listeners\CustomerEventsHandler@onCustomerLogout');
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Webkul\Product\Contracts\Criteria;
use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;
use Webkul\Attribute\Repositories\AttributeRepository;
/**
* Class MyCriteria.
*
* @package namespace App\Criteria;
*/
class FeaturedProductsCriteria implements CriteriaInterface
{
/**
* @var AttributeRepository
*/
protected $attribute;
/**
* @param Webkul\Attribute\Repositories\AttributeRepository $attribute
* @return void
*/
public function __construct(AttributeRepository $attribute)
{
$this->attribute = $attribute;
}
/**
* Apply criteria in query repository
*
* @param string $model
* @param RepositoryInterface $repository
*
* @return mixed
*/
public function apply($model, RepositoryInterface $repository)
{
$attribute = $this->attribute->findOneByField('code', 'featured');
$model = $model->leftJoin('product_attribute_values as filter_featured', 'products.id', '=', 'filter_featured.product_id');
$model->where('filter_featured.boolean_value', 1)
->where('filter_featured.attribute_id', $attribute->id);
return $model;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Webkul\Product\Contracts\Criteria;
use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;
use Webkul\Attribute\Repositories\AttributeRepository;
/**
* Class MyCriteria.
*
* @package namespace App\Criteria;
*/
class NewProductsCriteria implements CriteriaInterface
{
/**
* @var AttributeRepository
*/
protected $attribute;
/**
* @param Webkul\Attribute\Repositories\AttributeRepository $attribute
* @return void
*/
public function __construct(AttributeRepository $attribute)
{
$this->attribute = $attribute;
}
/**
* Apply criteria in query repository
*
* @param string $model
* @param RepositoryInterface $repository
*
* @return mixed
*/
public function apply($model, RepositoryInterface $repository)
{
$attribute = $this->attribute->findOneByField('code', 'new');
$model = $model->leftJoin('product_attribute_values as filter_new', 'products.id', '=', 'filter_new.product_id');
$model->where('filter_new.boolean_value', 1)
->where('filter_new.attribute_id', $attribute->id);
return $model;
}
}

View File

@ -185,27 +185,7 @@ class Product extends Model
$attributeModel = $this->attribute_family->custom_attributes()->where('attributes.code', $key)->first();
if($attributeModel) {
$channel = request()->get('channel') ?: core()->getCurrentChannelCode();
$locale = request()->get('locale') ?: app()->getLocale();
if($attributeModel->value_per_channel) {
if($attributeModel->value_per_locale) {
$attributeValue = $this->attribute_values()->where('channel', $channel)->where('locale', $locale)->where('attribute_id', $attributeModel->id)->first();
} else {
$attributeValue = $this->attribute_values()->where('channel', $channel)->where('attribute_id', $attributeModel->id)->first();
}
} else {
if($attributeModel->value_per_locale) {
$attributeValue = $this->attribute_values()->where('locale', $locale)->where('attribute_id', $attributeModel->id)->first();
} else {
$attributeValue = $this->attribute_values()->where('attribute_id', $attributeModel->id)->first();
}
}
$this->attributes[$key] = $attributeValue[ProductAttributeValue::$attributeTypeFields[$attributeModel->type]];
}
$this->attributes[$key] = $this->getCustomAttributeValue($attributeModel);
return $this->getAttributeValue($key);
}
@ -225,36 +205,49 @@ class Product extends Model
$hiddenAttributes = $this->getHidden();
if(isset($this->id)) {
$channel = request()->get('channel') ?: core()->getCurrentChannelCode();
$locale = request()->get('locale') ?: app()->getLocale();
foreach ($this->attribute_family->custom_attributes as $attribute) {
if (in_array($attribute->code, $hiddenAttributes)) {
continue;
}
if($attribute->value_per_channel) {
if($attribute->value_per_locale) {
$attributeValue = $this->attribute_values()->where('channel', $channel)->where('locale', $locale)->where('attribute_id', $attribute->id)->first();
} else {
$attributeValue = $this->attribute_values()->where('channel', $channel)->where('attribute_id', $attribute->id)->first();
}
} else {
if($attribute->value_per_locale) {
$attributeValue = $this->attribute_values()->where('locale', $locale)->where('attribute_id', $attribute->id)->first();
} else {
$attributeValue = $this->attribute_values()->where('attribute_id', $attribute->id)->first();
}
}
$attributes[$attribute->code] = $attributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]];
$attributes[$attribute->code] = $this->getCustomAttributeValue($attribute);
}
}
return $attributes;
}
/**
* Get an product attribute value.
*
* @return mixed
*/
public function getCustomAttributeValue($attribute)
{
if(!$attribute)
return;
$channel = request()->get('channel') ?: core()->getDefaultChannelCode();
$locale = request()->get('locale') ?: app()->getLocale();
if($attribute->value_per_channel) {
if($attribute->value_per_locale) {
$attributeValue = $this->attribute_values()->where('channel', $channel)->where('locale', $locale)->where('attribute_id', $attribute->id)->first();
} else {
$attributeValue = $this->attribute_values()->where('channel', $channel)->where('attribute_id', $attribute->id)->first();
}
} else {
if($attribute->value_per_locale) {
$attributeValue = $this->attribute_values()->where('locale', $locale)->where('attribute_id', $attribute->id)->first();
} else {
$attributeValue = $this->attribute_values()->where('attribute_id', $attribute->id)->first();
}
}
return $attributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]];
}
/**
* Overrides the default Eloquent query builder
*

View File

@ -37,21 +37,10 @@ class Review extends AbstractProduct
return $product->reviews()->where('status', 'approved')->count();
}
/**
* Returns the formated created at date
*
* @param ProductReview $review
* @return integer
*/
public function formatDate($reviewCreatedAt)
{
return core()->formatDate($reviewCreatedAt, 'd, M Y');
}
/**
* Returns the total rating of the product
*
* @param Product $product
* @param Product $product
* @return integer
*/
public function getTotalRating($product)

View File

@ -14,6 +14,8 @@ use Webkul\Product\Contracts\Criteria\SortCriteria;
use Webkul\Product\Contracts\Criteria\AttributeToSelectCriteria;
use Webkul\Product\Contracts\Criteria\FilterByAttributesCriteria;
use Webkul\Product\Contracts\Criteria\FilterByCategoryCriteria;
use Webkul\Product\Contracts\Criteria\NewProductsCriteria;
use Webkul\Product\Contracts\Criteria\FeaturedProductsCriteria;
use Illuminate\Database\Eloquent\ModelNotFoundException;
/**
@ -423,4 +425,54 @@ class ProductRepository extends Repository
get_class($this->model), $slug
);
}
/**
* Returns newly added product
*
* @return Collection
*/
public function getNewProducts()
{
$this->pushCriteria(app(NewProductsCriteria::class));
$this->pushCriteria(app(AttributeToSelectCriteria::class)->addAttribueToSelect([
'name',
'description',
'short_description',
'price',
'special_price',
'special_price_from',
'special_price_to'
]));
$params = request()->input();
return $this->scopeQuery(function($query) {
return $query->distinct()->addSelect('products.*')->orderBy('id', 'desc');
})->paginate(4, ['products.id']);
}
/**
* Returns featured product
*
* @return Collection
*/
public function getFeaturedProducts()
{
$this->pushCriteria(app(FeaturedProductsCriteria::class));
$this->pushCriteria(app(AttributeToSelectCriteria::class)->addAttribueToSelect([
'name',
'description',
'short_description',
'price',
'special_price',
'special_price_from',
'special_price_to'
]));
$params = request()->input();
return $this->scopeQuery(function($query) {
return $query->distinct()->addSelect('products.*')->orderBy('id', 'desc');
})->paginate(4, ['products.id']);
}
}

View File

@ -13,10 +13,8 @@ use Webkul\Product\Product\View as ProductView;
use Cart;
/**
* Cart controller for the customer
* and guest users for adding and
* removing the products in the
* cart.
* Cart controller for the customer and guest users for adding and
* removing the products in the cart.
*
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
@ -25,9 +23,7 @@ class CartController extends Controller
{
/**
* Protected Variables that
* holds instances of the
* repository classes.
* Protected Variables that holds instances of the repository classes.
*
* @param Array $_config
* @param $cart
@ -85,9 +81,7 @@ class CartController extends Controller
}
/**
* Function for guests
* user to add the product
* in the cart.
* Function for guests user to add the product in the cart.
*
* @return Mixed
*/
@ -101,8 +95,7 @@ class CartController extends Controller
}
/**
* Removes the item from
* the cart if it exists
* Removes the item from the cart if it exists
*
* @param integer $itemId
*/
@ -113,8 +106,7 @@ class CartController extends Controller
}
/**
* Updates the quantity of the
* items present in the cart.
* Updates the quantity of the items present in the cart.
*
* @return response
*/

View File

@ -1,10 +1,9 @@
<?php
namespace Webkul\Shop\Http\ViewComposers\Categories;
namespace Webkul\Shop\Http\ViewComposers;
use Illuminate\View\View;
use Illuminate\Support\Collection;
use Webkul\Category\Repositories\CategoryRepository as Category;
@ -14,7 +13,6 @@ use Webkul\Category\Repositories\CategoryRepository as Category;
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CategoryComposer
{
/**
@ -36,13 +34,20 @@ class CategoryComposer
$this->category = $category;
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$collected_cat = array();
$categories = $this->category->getCategoryTree();
foreach ($categories as $category) {
array_push($collected_cat, collect($category));
$categories = [];
foreach ($this->category->getCategoryTree() as $category) {
array_push($categories, collect($category));
}
$view->with('categories', $collected_cat);
$view->with('categories', $categories);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace Webkul\Shop\Http\ViewComposers;
use Illuminate\View\View;
use Illuminate\Support\Collection;
use Webkul\Product\Repositories\ProductRepository as Product;
/**
* Featured Products page
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class FeaturedProductListComposer
{
/**
* ProductRepository object
*
* @var array
*/
protected $product;
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function __construct(Product $product)
{
$this->product = $product;
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$products = $this->product->getFeaturedProducts();
$view->with('products', $products);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace Webkul\Shop\Http\ViewComposers;
use Illuminate\View\View;
use Illuminate\Support\Collection;
use Webkul\Product\Repositories\ProductRepository as Product;
/**
* New Products page
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class NewProductListComposer
{
/**
* ProductRepository object
*
* @var array
*/
protected $product;
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function __construct(Product $product)
{
$this->product = $product;
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$products = $this->product->getNewProducts();
$view->with('products', $products);
}
}

View File

@ -17,17 +17,19 @@ class ComposerServiceProvider extends ServiceProvider
*/
public function boot()
{
//using the class based composers...
View::composer(['shop::layouts.header.index', 'shop::layouts.footer.footer'], 'Webkul\Shop\Http\ViewComposers\Categories\CategoryComposer');
}
View::composer(
['shop::layouts.header.index', 'shop::layouts.footer.footer'],
'Webkul\Shop\Http\ViewComposers\CategoryComposer'
);
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
View::composer(
['shop::home.new-products'],
'Webkul\Shop\Http\ViewComposers\NewProductListComposer'
);
View::composer(
['shop::home.featured-products'],
'Webkul\Shop\Http\ViewComposers\FeaturedProductListComposer'
);
}
}
}

View File

@ -2,7 +2,11 @@
<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">
<i :class="[show ? 'icon arrow-down-icon mt-15' : 'icon dropdown-right-icon mt-15']"
v-if="haveChildren || item.parent_id == null" @click="showOrHide"></i>
<ul v-if="haveChildren && show">
<category-item
v-for="(child, index) in item.children"
:key="index"
@ -12,25 +16,35 @@
</li>
</template>
<script>
// define the item component
export default {
props: {
item: Object,
url: String,
},
data(){
return {
items_count:0
items_count:0,
show: false,
};
},
mounted: function() {
if(window.innerWidth > 770){
this.show = true;
}
},
computed: {
haveChildren() {
return this.item.children.length ? true : false;
}
},
methods: {
showOrHide: function() {
this.show = !this.show;
}
}
}
</script>
</script>

View File

@ -17,10 +17,8 @@
</template>
<script>
// define the item component
export default {
props: {
categories: {
type: [Array, String, Object],
@ -29,17 +27,15 @@ export default {
},
url: String
},
data(){
return {
items_count:0
};
},
computed: {
items () {
return JSON.parse(this.categories)
}
},
}
</script>
</script>

View File

@ -213,10 +213,6 @@ section.slider-block {
margin-bottom: 21px;
user-select: none;
.search-suggestion {
display: none;
}
.header-top {
margin-bottom: 16px;
display: flex;
@ -421,7 +417,6 @@ section.slider-block {
}
}
}
ul.right-responsive {
display: none;
@ -478,6 +473,10 @@ section.slider-block {
position: relative;
}
.nav li > .icon{
display: none;
}
.nav {
vertical-align: top;
display: inline-block;
@ -498,10 +497,15 @@ section.slider-block {
margin-bottom: 1px;
}
.nav > li > a .icon{
display: none;
}
.nav > li:last-child {
display:flex; align-items:center;
border-radius: 0 0 4px 0;
float:right;
display: none;
img {
margin-right:6px;
@ -560,9 +564,45 @@ section.slider-block {
right: 10px;
}
}
.search-responsive {
display: none;
.search-content {
border-bottom: 1px solid #e8e8e8;
height: 48px;
.search {
width: 70%;
margin-left: 20px;
height: 30px;
border: none;
font-size: 16px;
position: absolute;
}
.right {
float: right;
}
.suggestion {
position: absolute;
margin-left:20px;
}
}
.search-content:first-child {
border-top: 1px solid #e8e8e8;
}
}
.responsive-nav {
display: none;
}
}
@media all and (max-width: 720px) {
.header-bottom {
display: none !important;
}
@ -583,6 +623,47 @@ section.slider-block {
display: flex !important;
}
.responsive-nav {
margin-top: 20px;
display: none;
.nav a {
display:inline-block;
color: $font-color;
text-decoration: none;
padding: 12px 4.8px 12px 8px;
text-transform: uppercase;
letter-spacing: 2px;
position: relative;
width: 90%;
}
.nav li > .icon{
float: right;
}
.nav li a > .icon{
display: none;
}
.nav > li {
border-bottom: 1px solid $border-color;
}
.nav li:first-child {
border-top: 1px solid $border-color;
}
.nav > li:last-child {
float:none;
height: 45px;
display: none;
img {
margin-right:6px;
}
}
}
}
//footer responsive with out media query.
@ -1001,6 +1082,26 @@ section.product-detail {
div.product-image-group {
margin-right: 30px;
width: 604px;
height: 650px;
max-width: 604px;
.loader {
border: 16px solid #f3f3f3;
border-top: 16px solid #3498db;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 2s linear infinite;
margin-left: 20%;
position: absolute;
margin-top: 200px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
div {
display: flex;
@ -1010,17 +1111,17 @@ section.product-detail {
display: flex;
flex-direction: column;
margin-right: 4px;
height: 480px;
min-width: 120px;
overflow: hidden;
position: relative;
justify-content: flex-start;
max-height: 480px;
.thumb-frame {
border: 2px solid transparent;
background: #F2F2F2;
width: 120px;
height: 120px;
max-height: 120px;
&.active {
border-color: #979797;
@ -1069,52 +1170,65 @@ section.product-detail {
background: #F2F2F2;
width: 100%;
max-height: 480px;
height: 100%;
img {
width: 100%;
height: 480px;
height: auto;
max-height: 480px;
}
.wishlist-icon {
position: absolute;
height: 32px;
width: 32px;
top: 15px;
right: 15px;
.whishlist-icon {
margin-top: -480px;
float: right;
margin-right: 10px;
}
.share-icon {
margin-top: -480px;
float: right;
margin-right: 40px;
}
.wishlist {
position: absolute;
height: 32px;
width: 32px;
top: 15px;
right: 48px;
top: 10px;
right: 12px;
}
.share {
position: absolute;
top: 10px;
right: 45px;
}
}
}
.add-to-buttons {
display: flex;
display: none;
flex-direction: row;
margin-top: 10px;
justify-content: space-between;
.addtocart {
border-radius: 0px;
width: 49%;
background: black;
white-space: nowrap;
}
.buynow {
border-radius: 0px;
width: 49%;
float:right;
white-space: nowrap;
}
}
}
.details {
width: 47.5%;
width: 50%;
.product-price {
margin-bottom: 14px;
@ -1190,6 +1304,76 @@ section.product-detail {
}
// product pages css ends here
// product pages responsive css start here
@media only screen and (max-width: 720px){
section.product-detail div.layouter form {
flex-direction: column;
div.product-image-group {
margin-right: 0px;
max-width: none;
width: auto;
.loader {
margin-left: 47%;
}
div {
flex-direction: column-reverse;
.thumb-list {
height: 120px;
margin-top: 5px;
flex-direction: row;
overflow-x: scroll;
margin-right: 0px;
.thumb-frame {
img {
height: 100%;
width: auto;
}
}
.gallery-control {
display: none;
}
}
.product-hero-image{
display: flex;
img {
margin-left: auto;
margin-right: auto;
width: 480px;
}
}
}
}
.details {
width: 100%;
margin-top: 20px;
}
}
}
@media only screen and (max-width: 510px){
section.product-detail div.layouter form {
div.product-image-group {
.product-hero-image img {
width: 100% !important;
}
}
}
}
//product pages responsive css end here
//rating and reviews of product pages
.rating-reviews {
@ -1364,11 +1548,7 @@ section.cart {
.towishlist {
color : $brand-color;
}
}
.error-message {
color: #ff5656;
margin-top: 17px;
}
}
}
@ -1608,17 +1788,8 @@ section.cart {
}
// checkout ends here
.order-success-content {
padding: 40px 0;
.btn {
display: inline-block;
}
}
// checkout responsive start here
@media only screen and (max-width: 770px) {
.checkout-process {
.col-main {
width: 100%;
@ -1650,7 +1821,6 @@ section.cart {
display: none;
}
}
}
// checkout responsive end here
@ -1900,3 +2070,4 @@ section.review {
}
// customer section css end here

View File

@ -13,8 +13,8 @@
.icon-menu-close {
background-image:URL('../images/icon-menu-close.svg');
width: 8px;
height: 8px;
width: 24px;
height: 24px;
margin-left:auto;
margin-bottom: 2px;
}

View File

@ -71,6 +71,10 @@ body {
//margin-top
.mt-5 {
margin-top: 5px;
}
.mt-10 {
margin-top: 10px;
}
@ -299,4 +303,5 @@ body {
width: 100%;
float: none;
padding-right: 0px;
}
}

View File

@ -1,6 +1,10 @@
<?php
return [
'home' => [
'featured-products' => 'Featured Products',
'new-products' => 'New Products'
],
'customer' => [
'signup-text' => [
'account_exists' => 'Already have an account',

View File

@ -1,31 +1,21 @@
<section class="featured-products">
<div class="featured-heading">
Featured Products<br/>
<span class="featured-seperator" style="color:lightgrey;">_____</span>
</div>
@if($products->count())
<section class="featured-products">
<div class="featured-grid product-grid-4">
@for($i=0; $i<4; $i++)
<div class="product-card">
<div class="product-image">
<img src="vendor/webkul/shop/assets/images/grid.png" />
</div>
<div class="product-name">
<span>Red Black Tees</span>
</div>
<div class="product-price">
<span>$65.00</span>
</div>
<div class="product-ratings mb-10">
<span>
<img src="vendor/webkul/shop/assets/images/5star.svg" />
</span>
</div>
<div class="cart-fav-seg">
<button class="btn btn-md btn-primary addtocart">Add to Cart</button>
<span><img src="vendor/webkul/shop/assets/images/wishadd.svg" /></span>
</div>
<div class="featured-heading">
{{ __('shop::app.home.featured-products') }}<br/>
<span class="featured-seperator" style="color:lightgrey;">_____</span>
</div>
@endfor
</div>
</section>
<div class="featured-grid product-grid-4">
@foreach ($products as $product)
@include ('shop::products.list.card', ['product' => $product])
@endforeach
</div>
</section>
@endif

View File

@ -1,92 +1,21 @@
<section class="featured-products">
<div class="featured-heading">
New Products<br/>
<span class="featured-seperator" style="color:lightgrey;">_____</span>
</div>
@if($products->count())
<section class="featured-products">
<div class="product-grid-4">
<div class="product-card">
<div class="product-image">
<img src="vendor/webkul/shop/assets/images/new.png" />
</div>
<div class="product-name">
<span>Red Black Tees</span>
</div>
<div class="product-price">
<span>$65.00</span>
</div>
<div class="product-ratings mb-10">
<span>
<img src="vendor/webkul/shop/assets/images/5star.svg" />
</span>
</div>
<div class="cart-fav-seg">
<button class="btn btn-md btn-primary addtocart">Add to Cart</button>
<span><img src="vendor/webkul/shop/assets/images/wishadd.svg" /></span>
</div>
<div class="featured-heading">
{{ __('shop::app.home.new-products') }}<br/>
<span class="featured-seperator" style="color:lightgrey;">_____</span>
</div>
<div class="product-card">
<div class="product-image">
<img src="vendor/webkul/shop/assets/images/new.png" />
</div>
<div class="product-name">
<span>Red Black Tees</span>
</div>
<div class="product-price">
<span>$65.00</span>
</div>
<div class="product-ratings mb-10">
<span>
<img src="vendor/webkul/shop/assets/images/5star.svg" />
</span>
</div>
<div class="cart-fav-seg">
<button class="btn btn-md btn-primary addtocart">Add to Cart</button>
<span><img src="vendor/webkul/shop/assets/images/wishadd.svg" /></span>
</div>
</div>
<div class="product-grid-4">
@foreach ($products as $product)
<div class="product-card">
<div class="product-image">
<img src="vendor/webkul/shop/assets/images/new.png" />
</div>
<div class="product-name">
<span>Red Black Tees</span>
</div>
<div class="product-price">
<span>$65.00</span>
</div>
<div class="product-ratings mb-10">
<span>
<img src="vendor/webkul/shop/assets/images/5star.svg" />
</span>
</div>
<div class="cart-fav-seg">
<button class="btn btn-md btn-primary addtocart">Add to Cart</button>
<span><img src="vendor/webkul/shop/assets/images/wishadd.svg" /></span>
</div>
</div>
@include ('shop::products.list.card', ['product' => $product])
@endforeach
<div class="product-card">
<div class="product-image">
<img src="vendor/webkul/shop/assets/images/new.png" />
</div>
<div class="product-name">
<span>Red Black Tees</span>
</div>
<div class="product-price">
<span>$65.00</span>
</div>
<div class="product-ratings mb-10">
<span>
<img src="vendor/webkul/shop/assets/images/5star.svg" />
</span>
</div>
<div class="cart-fav-seg">
<button class="btn btn-md btn-primary addtocart">Add to Cart</button>
<span><img src="vendor/webkul/shop/assets/images/wishadd.svg" /></span>
</div>
</div>
</div>
</section>
</section>
@endif

View File

@ -284,13 +284,172 @@
</li>
</ul>
{{-- <li class="cart-box"><span class="icon cart-icon"></span></li> --}}
<li class="menu-box" ><span class="icon sortable-icon" id="sortable"></span></li>
<li class="menu-box" ><span class="icon sortable-icon" id="hammenu"></span></li>
</ul>
</div>
</div>
<div class="header-bottom" id="header-bottom">
@include('shop::layouts.header.nav-menu.navmenu')
@include('shop::layouts.header.nav-menu.navmenu')
</div>
</div>
<div class="search-responsive">
<div class="search-content">
<i class="icon search-icon mt-10"></i>
<input class="search mt-5">
<i class="icon icon-menu-back right mt-10"></i>
</div>
<div class="search-content">
<i class="icon search-icon mt-10"></i>
<span class="suggestion mt-15">Designer sarees</span>
</div>
</div>
<div class="responsive-nav">
<category-nav categories='@json($categories)' url="{{url()->to('/')}}"></category-nav>
</div>
</div>
@push('scripts')
<script>
document.onreadystatechange = function () {
var state = document.readyState
var galleryTemplate = document.getElementById('product-gallery-template');
var addTOButton = document.getElementsByClassName('add-to-buttons')[0];
if(galleryTemplate){
if (state == 'interactive') {
galleryTemplate.style.display="none";
} else {
document.getElementById('loader').style.display="none";
addTOButton.style.display="flex";
}
}
}
window.onload = function() {
var hamMenu = document.getElementById("hammenu");
var search = document.getElementById("search");
var sort = document.getElementById("sort");
var filter = document.getElementById("filter");
var searchResponsive = document.getElementsByClassName('search-responsive')[0];
var sortLimit = document.getElementsByClassName('reponsive-sorter-limiter')[0];
var layerFilter = document.getElementsByClassName('responsive-layred-filter')[0];
var navResponsive = document.getElementsByClassName('responsive-nav')[0];
var thumbList = document.getElementsByClassName('thumb-list')[0];
var thumbFrame = document.getElementsByClassName('thumb-frame');
var productHeroImage = document.getElementsByClassName('product-hero-image')[0];
// for product page resize image
if(thumbList && productHeroImage){
thumbList.style.maxHeight = productHeroImage.offsetHeight + "px";
for(let i=0 ; i < thumbFrame.length ; i++){
thumbFrame[i].style.height = (productHeroImage.offsetHeight/4) + "px";
}
}
search.addEventListener("click", header);
hamMenu.addEventListener("click", header);
if(sort && filter){
sort.addEventListener("click", sortFilter);
filter.addEventListener("click", sortFilter);
}
window.addEventListener('resize', function(){
if(window.innerWidth > 720){
searchResponsive.style.display = 'none';
navResponsive.style.display = 'none';
if(layerFilter && sortLimit){
layerFilter.style.display ="none";
sortLimit.style.display ="none";
}
}
if(window.innerWidth < 1313 && window.innerWidth > 720){
if(thumbList){
thumbList.style.maxHeight = productHeroImage.offsetHeight + "px";
for(let i=0 ; i < thumbFrame.length ; i++){
thumbFrame[i].style.height = (productHeroImage.offsetHeight/4) + "px";
}
}
}else {
for(let i=0 ; i < thumbFrame.length ; i++){
thumbFrame[i].style.height = 120 + "px";
}
}
});
// for header responsive icon
function header(){
var className = document.getElementById(this.id).className;
if(className === 'icon search-icon' ){
search.classList.remove("search-icon");
search.classList.add("icon-menu-close");
hamMenu.classList.remove("icon-menu-close");
hamMenu.classList.add("sortable-icon");
searchResponsive.style.display = 'block';
navResponsive.style.display = 'none';
}else if(className === 'icon sortable-icon'){
hamMenu.classList.remove("sortable-icon");
hamMenu.classList.add("icon-menu-close");
search.classList.remove("icon-menu-close");
search.classList.add("search-icon");
searchResponsive.style.display = 'none';
navResponsive.style.display = 'block';
}else{
search.classList.remove("icon-menu-close");
search.classList.add("search-icon");
hamMenu.classList.remove("icon-menu-close");
hamMenu.classList.add("sortable-icon");
searchResponsive.style.display = 'none';
navResponsive.style.display = 'none';
}
}
// for category page responsive filter & sort
function sortFilter(){
var className = document.getElementById(this.id).className;
if(className === 'icon sort-icon' ){
sort.classList.remove("sort-icon");
sort.classList.add("icon-menu-close");
filter.classList.remove("icon-menu-close");
filter.classList.add("filter-icon");
sortLimit.style.display ="flex";
sortLimit.style.justifyContent="space-between";
layerFilter.style.display ="none";
}else if(className === 'icon filter-icon'){
filter.classList.remove("filter-icon");
filter.classList.add("icon-menu-close");
sort.classList.remove("icon-menu-close");
sort.classList.add("sort-icon");
layerFilter.style.display ="block";
sortLimit.style.display ="none";
}else{
sort.classList.remove("icon-menu-close");
sort.classList.add("sort-icon");
filter.classList.remove("icon-menu-close");
filter.classList.add("filter-icon");
sortLimit.style.display ="none";
layerFilter.style.display ="none";
}
}
}
</script>
@endpush

View File

@ -54,48 +54,5 @@
@stop
@push('scripts')
<script>
window.onload = function() {
var sort = document.getElementById("sort");
var filter = document.getElementById("filter");
var sortLimit = document.getElementsByClassName('reponsive-sorter-limiter')[0];
var layerFilter = document.getElementsByClassName('responsive-layred-filter')[0];
sort.addEventListener("click", sortFilter);
filter.addEventListener("click", sortFilter);
function sortFilter(){
var className = document.getElementById(this.id).className;
if(className === 'icon sort-icon' ){
sort.classList.remove("sort-icon");
sort.classList.add("cross-icon");
filter.classList.remove("cross-icon");
filter.classList.add("filter-icon");
sortLimit.style.display ="flex";
sortLimit.style.justifyContent="space-between";
layerFilter.style.display ="none";
}else if(className === 'icon filter-icon'){
filter.classList.remove("filter-icon");
filter.classList.add("cross-icon");
sort.classList.remove("cross-icon");
sort.classList.add("sort-icon");
layerFilter.style.display ="block";
sortLimit.style.display ="none";
}else{
sort.classList.remove("cross-icon");
sort.classList.add("sort-icon");
filter.classList.remove("cross-icon");
filter.classList.add("filter-icon");
sortLimit.style.display ="none";
layerFilter.style.display ="none";
}
}
}
</script>
@endpush

View File

@ -104,7 +104,7 @@
{{ __('shop::app.products.by', ['name' => $review->customer->name]) }}
</span>
<span class="when">
{{ $reviewHelper->formatDate($review->created_at) }}
{{ core()->formatDate($review->created_at) }}
</span>
</div>
</div>

View File

@ -80,3 +80,4 @@
@endsection

View File

@ -3,9 +3,17 @@
<div class="product-image-group">
<div class="loader" id="loader">
</div>
<product-gallery></product-gallery>
@include ('shop::products.product-add')
</div>
@push('scripts')
<script type="text/x-template" id="product-gallery-template">
@ -37,7 +45,6 @@
@include('shop::products.wishlist')
</div>
</div>
</script>

View File

@ -60,7 +60,7 @@
</span>
<span class="when">
{{ $reviewHelper->formatDate($review->created_at) }}
{{ core()->formatDate($review->created_at) }}
</span>
</div>
</div>

View File

@ -7,7 +7,7 @@
</div>
<div class="product-grid max-4-col">
@foreach ($product->up_sells()->paginate(4) as $up_sell_product)
@include ('shop::products.list.card', ['product' => $up_sell_product])

View File

@ -200,7 +200,7 @@ class ProductGrid
public function __construct(AttributeRepository $attributes) {
$this->channel = request()->get('channel') ?: core()->getCurrentChannelCode();
$this->channel = request()->get('channel') ?: core()->getDefaultChannelCode();
$this->locale = request()->get('locale') ?: app()->getLocale();
$this->attributes = $attributes;

View File

@ -13,8 +13,8 @@
.icon-menu-close {
background-image: URL("../images/icon-menu-close.svg");
width: 8px;
height: 8px;
width: 24px;
height: 24px;
margin-left: auto;
margin-bottom: 2px;
}
@ -341,6 +341,10 @@ body {
margin-bottom: 90px;
}
.mt-5 {
margin-top: 5px;
}
.mt-10 {
margin-top: 10px;
}
@ -750,10 +754,6 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
user-select: none;
}
.header .search-suggestion {
display: none;
}
.header .header-top {
margin-bottom: 16px;
display: -webkit-box;
@ -1078,6 +1078,10 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
position: relative;
}
.header .header-bottom .nav li > .icon {
display: none;
}
.header .header-bottom .nav {
vertical-align: top;
display: inline-block;
@ -1097,6 +1101,10 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
margin-bottom: 1px;
}
.header .header-bottom .nav > li > a .icon {
display: none;
}
.header .header-bottom .nav > li:last-child {
display: -webkit-box;
display: -ms-flexbox;
@ -1106,6 +1114,7 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
align-items: center;
border-radius: 0 0 4px 0;
float: right;
display: none;
}
.header .header-bottom .nav > li:last-child img {
@ -1162,6 +1171,41 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
right: 10px;
}
.header .search-responsive {
display: none;
}
.header .search-responsive .search-content {
border-bottom: 1px solid #e8e8e8;
height: 48px;
}
.header .search-responsive .search-content .search {
width: 70%;
margin-left: 20px;
height: 30px;
border: none;
font-size: 16px;
position: absolute;
}
.header .search-responsive .search-content .right {
float: right;
}
.header .search-responsive .search-content .suggestion {
position: absolute;
margin-left: 20px;
}
.header .search-responsive .search-content:first-child {
border-top: 1px solid #e8e8e8;
}
.header .responsive-nav {
display: none;
}
@media all and (max-width: 720px) {
.header-bottom {
display: none !important;
@ -1180,6 +1224,40 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
display: -ms-flexbox !important;
display: flex !important;
}
.responsive-nav {
margin-top: 20px;
display: none;
}
.responsive-nav .nav a {
display: inline-block;
color: #242424;
text-decoration: none;
padding: 12px 4.8px 12px 8px;
text-transform: uppercase;
letter-spacing: 2px;
position: relative;
width: 90%;
}
.responsive-nav .nav li > .icon {
float: right;
}
.responsive-nav .nav li a > .icon {
display: none;
}
.responsive-nav .nav > li {
border-bottom: 1px solid #E8E8E8;
}
.responsive-nav .nav li:first-child {
border-top: 1px solid #E8E8E8;
}
.responsive-nav .nav > li:last-child {
float: none;
height: 45px;
display: none;
}
.responsive-nav .nav > li:last-child img {
margin-right: 6px;
}
}
.footer {
@ -1616,6 +1694,44 @@ section.product-detail div.layouter form {
section.product-detail div.layouter form div.product-image-group {
margin-right: 30px;
width: 604px;
height: 650px;
max-width: 604px;
}
section.product-detail div.layouter form div.product-image-group .loader {
border: 16px solid #f3f3f3;
border-top: 16px solid #3498db;
border-radius: 50%;
width: 50px;
height: 50px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
margin-left: 20%;
position: absolute;
margin-top: 200px;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
section.product-detail div.layouter form div.product-image-group div {
@ -1637,20 +1753,20 @@ section.product-detail div.layouter form div.product-image-group div .thumb-list
-ms-flex-direction: column;
flex-direction: column;
margin-right: 4px;
height: 480px;
min-width: 120px;
overflow: hidden;
position: relative;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
max-height: 480px;
}
section.product-detail div.layouter form div.product-image-group div .thumb-list .thumb-frame {
border: 2px solid transparent;
background: #F2F2F2;
width: 120px;
height: 120px;
max-height: 120px;
}
section.product-detail div.layouter form div.product-image-group div .thumb-list .thumb-frame.active {
@ -1698,55 +1814,67 @@ section.product-detail div.layouter form div.product-image-group div .product-he
background: #F2F2F2;
width: 100%;
max-height: 480px;
height: 100%;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image img {
width: 100%;
height: 480px;
height: auto;
max-height: 480px;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image .wishlist-icon {
position: absolute;
height: 32px;
width: 32px;
top: 15px;
right: 15px;
section.product-detail div.layouter form div.product-image-group div .product-hero-image .whishlist-icon {
margin-top: -480px;
float: right;
margin-right: 10px;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image .share-icon {
margin-top: -480px;
float: right;
margin-right: 40px;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image .wishlist {
position: absolute;
height: 32px;
width: 32px;
top: 15px;
right: 48px;
top: 10px;
right: 12px;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image .share {
position: absolute;
top: 10px;
right: 45px;
}
section.product-detail div.layouter form div.product-image-group .add-to-buttons {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
display: none;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
margin-top: 10px;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
section.product-detail div.layouter form div.product-image-group .add-to-buttons .addtocart {
border-radius: 0px;
width: 49%;
background: black;
white-space: nowrap;
}
section.product-detail div.layouter form div.product-image-group .add-to-buttons .buynow {
border-radius: 0px;
width: 49%;
float: right;
white-space: nowrap;
}
section.product-detail div.layouter form .details {
width: 47.5%;
width: 50%;
}
section.product-detail div.layouter form .details .product-price {
@ -1816,6 +1944,66 @@ section.product-detail div.layouter form .details .attributes {
border-bottom: solid 1px rgba(162, 162, 162, 0.2);
}
@media only screen and (max-width: 720px) {
section.product-detail div.layouter form {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
section.product-detail div.layouter form div.product-image-group {
margin-right: 0px;
max-width: none;
width: auto;
}
section.product-detail div.layouter form div.product-image-group .loader {
margin-left: 47%;
}
section.product-detail div.layouter form div.product-image-group div {
-webkit-box-orient: vertical;
-webkit-box-direction: reverse;
-ms-flex-direction: column-reverse;
flex-direction: column-reverse;
}
section.product-detail div.layouter form div.product-image-group div .thumb-list {
height: 120px;
margin-top: 5px;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
overflow-x: scroll;
margin-right: 0px;
}
section.product-detail div.layouter form div.product-image-group div .thumb-list .thumb-frame img {
height: 100%;
width: auto;
}
section.product-detail div.layouter form div.product-image-group div .thumb-list .gallery-control {
display: none;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
section.product-detail div.layouter form div.product-image-group div .product-hero-image img {
margin-left: auto;
margin-right: auto;
width: 480px;
}
section.product-detail div.layouter form .details {
width: 100%;
margin-top: 20px;
}
}
@media only screen and (max-width: 510px) {
section.product-detail div.layouter form div.product-image-group .product-hero-image img {
width: 100% !important;
}
}
.rating-reviews .rating-header {
font-weight: 600;
padding: 20px 0;
@ -2017,11 +2205,6 @@ section.cart .cart-content .right-side {
color: #0041FF;
}
.cart-item-list .item .item-details .error-message {
color: #ff5656;
margin-top: 17px;
}
.order-summary h3 {
font-size: 16px;
margin-top: 0;
@ -2252,14 +2435,6 @@ section.cart .cart-content .right-side {
padding-left: 40px;
}
.order-success-content {
padding: 40px 0;
}
.order-success-content .btn {
display: inline-block;
}
@media only screen and (max-width: 770px) {
.checkout-process .col-main {
width: 100%;

View File

@ -30701,10 +30701,8 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
//
//
// define the item component
/* harmony default export */ __webpack_exports__["default"] = ({
props: {
categories: {
type: [Array, String, Object],
@ -30715,14 +30713,12 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
},
url: String
},
data: function data() {
return {
items_count: 0
};
},
computed: {
items: function items() {
return JSON.parse(this.categories);
@ -30846,27 +30842,41 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
//
//
//
//
//
//
//
// define the item component
/* harmony default export */ __webpack_exports__["default"] = ({
props: {
item: Object,
url: String
},
data: function data() {
return {
items_count: 0
items_count: 0,
show: false
};
},
mounted: function mounted() {
if (window.innerWidth > 770) {
this.show = true;
}
},
computed: {
haveChildren: function haveChildren() {
return this.item.children.length ? true : false;
}
},
methods: {
showOrHide: function showOrHide() {
this.show = !this.show;
}
}
});
@ -30886,7 +30896,18 @@ var render = function() {
: _vm._e()
]),
_vm._v(" "),
_vm.haveChildren
_vm.haveChildren || _vm.item.parent_id == null
? _c("i", {
class: [
_vm.show
? "icon arrow-down-icon mt-15"
: "icon dropdown-right-icon mt-15"
],
on: { click: _vm.showOrHide }
})
: _vm._e(),
_vm._v(" "),
_vm.haveChildren && _vm.show
? _c(
"ul",
_vm._l(_vm.item.children, function(child, index) {