Merge pull request #6 from bagisto/master

Merge with original repo
This commit is contained in:
Glenn Hermans 2020-03-02 22:38:29 +01:00 committed by GitHub
commit 28a3f7e56a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 1456 additions and 436 deletions

View File

@ -4,9 +4,10 @@ APP_VERSION=1.0.0
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_TIMEZONE='Asia/Kolkata'
APP_TIMEZONE=
APP_LOCALE=
LOG_CHANNEL=stack
APP_CURRENCY=USD
APP_CURRENCY=
DB_CONNECTION=mysql
DB_HOST=127.0.0.1

View File

@ -7,7 +7,7 @@ about: 'Report a general library issue.'
### Title
**Just a quick sentence to brief your trouble with Bagisto or something associated with it.**
**Please be calm, short and emaphasize on points.**
**Please be calm, short and emphasize on points.**
### Issue Description
**Description helps the developers to understand the bug. It describes the problem encountered or some after effect of some kind.**

View File

@ -3,9 +3,13 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Webkul\Product\Repositories\ProductRepository as Product;
use Webkul\Product\Helpers\GenerateProduct;
/**
* Class GenerateProducts
*
* @package App\Console\Commands
*/
class GenerateProducts extends Command
{
/**
@ -54,12 +58,24 @@ class GenerateProducts extends Command
if (! is_string($this->argument('value')) || ! is_numeric($this->argument('quantity'))) {
$this->info('Illegal parameters or value of parameters are passed');
} else {
if (strtolower($this->argument('value')) == 'product' || strtolower($this->argument('value')) == 'products') {
$quantity = intval($this->argument('quantity'));
if (strtolower($this->argument('value')) == 'product' || strtolower($this->argument('value')) == 'products') {
$quantity = (int)$this->argument('quantity');
// @see https://laravel.com/docs/6.x/artisan#writing-output
// @see https://symfony.com/doc/current/components/console/helpers/progressbar.html
$bar = $this->output->createProgressBar($quantity);
$this->line("Generating $quantity {$this->argument('value')}.");
$bar->start();
$generatedProducts = 0;
$this->generateProduct->generateDemoBrand();
while ($quantity > 0) {
try {
$result = $this->generateProduct->create();
$generatedProducts++;
$bar->advance();
} catch (\Exception $e) {
report($e);
continue;
@ -68,10 +84,13 @@ class GenerateProducts extends Command
$quantity--;
}
if ($result)
$this->info('Product(s) created successfully.');
else
if ($result) {
$bar->finish();
$this->info("\n$generatedProducts Product(s) created successfully.");
} else {
$this->info('Product(s) cannot be created successfully.');
}
} else {
$this->line('Sorry, this generate option is invalid.');
}

View File

@ -78,35 +78,57 @@ class install extends Command
{
$envExists = File::exists(base_path() . '/.env');
if (!$envExists) {
$this->info('Creating .env file');
$this->info('Creating the environment configuration file.');
$this->createEnvFile();
} else {
$this->info('Great! .env file aready exists');
$this->info('Great! your environment configuration file aready exists.');
}
}
/**
* Create a new .env file.
*/
public function createEnvFile()
{
try {
File::copy('.env.example', '.env');
Artisan::call('key:generate');
$this->envUpdate('APP_URL=http://localhost', ':8000');
$locale = $this->choice('Please select the default locale or press enter to continue', ['ar', 'en', 'fa', 'nl', 'pt_BR'], 1);
$this->envUpdate('APP_LOCALE=', $locale);
$TimeZones = timezone_identifiers_list();
$timezone = $this->anticipate('Please enter the default timezone', $TimeZones, date_default_timezone_get());
$this->envUpdate('APP_TIMEZONE=', $timezone);
$currency = $this->choice('Please enter the default currency', ['USD', 'EUR'], 'USD');
$this->envUpdate('APP_CURRENCY=', $currency);
$this->addDatabaseDetails();
} catch (\Exception $e) {
$this->error('Error in creating .env file, please create manually and then run `php artisan migrate` again');
$this->error('Error in creating .env file, please create it manually and then run `php artisan migrate` again.');
}
}
/**
* Add the database credentials to the .env file.
*/
public function addDatabaseDetails()
{
$dbName = $this->ask('What is your database name to be used by bagisto');
$dbUser = $this->anticipate('What is your database username', ['root']);
$dbPass = $this->secret('What is your database password');
$dbName = $this->ask('What is the database name to be used by bagisto?');
$dbUser = $this->anticipate('What is your database username?', ['root']);
$dbPass = $this->secret('What is your database password?');
$this->envUpdate('DB_DATABASE=', $dbName);
$this->envUpdate('DB_USERNAME=', $dbUser);
$this->envUpdate('DB_PASSWORD=', $dbPass);
}
/**
* Update the .env values.
*/
public static function envUpdate($key, $value)
{
$path = base_path() . '/.env';

View File

@ -78,7 +78,7 @@ return [
|
*/
'locale' => 'en',
'locale' => env('APP_LOCALE', 'en'),
/*
|--------------------------------------------------------------------------
@ -116,8 +116,8 @@ return [
| Here you may specify the base currency code for your application.
|
*/
'currency' => env('APP_CURRENCY','USD'),
'currency' => env('APP_CURRENCY', 'USD'),
/*
|--------------------------------------------------------------------------

View File

@ -56,8 +56,7 @@ class CartController extends Controller
CartRepository $cartRepository,
CartItemRepository $cartItemRepository,
WishlistRepository $wishlistRepository
)
{
) {
$this->guard = request()->has('token') ? 'api' : 'customer';
auth()->setDefaultDriver($this->guard);
@ -93,7 +92,8 @@ class CartController extends Controller
/**
* Store a newly created resource in storage.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function store($id)
@ -101,7 +101,7 @@ class CartController extends Controller
if (request()->get('is_buy_now')) {
Event::dispatch('shop.item.buy-now', $id);
}
Event::dispatch('checkout.cart.item.add.before', $id);
$result = Cart::addProduct($id, request()->except('_token'));
@ -110,12 +110,13 @@ class CartController extends Controller
$message = session()->get('warning') ?? session()->get('error');
return response()->json([
'error' => session()->get('warning')
], 400);
'error' => session()->get('warning')
], 400);
}
if ($customer = auth($this->guard)->user())
if ($customer = auth($this->guard)->user()) {
$this->wishlistRepository->deleteWhere(['product_id' => $id, 'customer_id' => $customer->id]);
}
Event::dispatch('checkout.cart.item.add.after', $result);
@ -124,9 +125,9 @@ class CartController extends Controller
$cart = Cart::getCart();
return response()->json([
'message' => 'Product added to cart successfully.',
'data' => $cart ? new CartResource($cart) : null
]);
'message' => __('shop::app.checkout.cart.item.success'),
'data' => $cart ? new CartResource($cart) : null
]);
}
/**
@ -136,11 +137,11 @@ class CartController extends Controller
*/
public function update()
{
foreach (request()->get('qty') as$qty) {
foreach (request()->get('qty') as $qty) {
if ($qty <= 0) {
return response()->json([
'message' => trans('shop::app.checkout.cart.quantity.illegal')
], 401);
'message' => trans('shop::app.checkout.cart.quantity.illegal')
], 401);
}
}
@ -159,9 +160,9 @@ class CartController extends Controller
$cart = Cart::getCart();
return response()->json([
'message' => 'Cart updated successfully.',
'data' => $cart ? new CartResource($cart) : null
]);
'message' => __('shop::app.checkout.cart.quantity.success'),
'data' => $cart ? new CartResource($cart) : null
]);
}
/**
@ -180,15 +181,16 @@ class CartController extends Controller
$cart = Cart::getCart();
return response()->json([
'message' => 'Cart removed successfully.',
'data' => $cart ? new CartResource($cart) : null
]);
'message' => __('shop::app.checkout.cart.item.success-remove'),
'data' => $cart ? new CartResource($cart) : null
]);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function destroyItem($id)
@ -204,9 +206,9 @@ class CartController extends Controller
$cart = Cart::getCart();
return response()->json([
'message' => 'Cart removed successfully.',
'data' => $cart ? new CartResource($cart) : null
]);
'message' => __('shop::app.checkout.cart.item.success-remove'),
'data' => $cart ? new CartResource($cart) : null
]);
}
/**
@ -228,8 +230,8 @@ class CartController extends Controller
$cart = Cart::getCart();
return response()->json([
'message' => 'Cart item moved to wishlist successfully.',
'data' => $cart ? new CartResource($cart) : null
]);
'message' => __('shop::app.checkout.cart.move-to-wishlist-success'),
'data' => $cart ? new CartResource($cart) : null
]);
}
}
}

View File

@ -565,6 +565,7 @@ return [
'file' => 'File',
'checkbox' => 'Checkbox',
'use_in_flat' => "Create in Product Flat Table",
'is_comparable' => "Attribute is comparable",
'default_null_option' => 'Create default empty option',
],
'families' => [

View File

@ -278,6 +278,18 @@
</select>
</div>
<div class="control-group">
<label for="is_comparable">{{ __('admin::app.catalog.attributes.is_comparable') }}</label>
<select class="control" id="is_comparable" name="is_comparable">
<option value="0" {{ $attribute->is_comparable ? '' : 'selected' }}>
{{ __('admin::app.catalog.attributes.no') }}
</option>
<option value="1" {{ $attribute->is_comparable ? 'selected' : '' }}>
{{ __('admin::app.catalog.attributes.yes') }}
</option>
</select>
</div>
{!! view_render_event('bagisto.admin.catalog.attribute.edit_form_accordian.configuration.controls.after', ['attribute' => $attribute]) !!}
</div>

View File

@ -56,7 +56,7 @@
<div class="control-group">
<label for="status">{{ __('admin::app.promotions.cart-rules.status') }}</label>
<label class="switch">
<input type="checkbox" id="status" name="status" value="1" {{ old('status') ? 'checked' : '' }}>
<span class="slider round"></span>
@ -140,16 +140,16 @@
<div class="control-group date">
<label for="starts_from">{{ __('admin::app.promotions.cart-rules.from') }}</label>
<date>
<datetime>
<input type="text" name="starts_from" class="control" value="{{ old('starts_from') }}"/>
</date>
</datetime>
</div>
<div class="control-group date">
<label for="ends_till">{{ __('admin::app.promotions.cart-rules.to') }}</label>
<date>
<datetime>
<input type="text" name="ends_till" class="control" value="{{ old('ends_till') }}"/>
</date>
</datetime>
</div>
<div class="control-group">
@ -427,11 +427,11 @@
attribute_type_indexes: {
'cart': 0,
'cart_item': 1,
'product': 2
},
},
condition_operators: {
'price': [{

View File

@ -56,7 +56,7 @@
<div class="control-group">
<label for="status">{{ __('admin::app.promotions.cart-rules.status') }}</label>
<label class="switch">
<input type="checkbox" id="status" name="status" value="{{ $cartRule->status }}" {{ $cartRule->status ? 'checked' : '' }}>
<span class="slider round"></span>
@ -144,16 +144,16 @@
<div class="control-group date">
<label for="starts_from">{{ __('admin::app.promotions.cart-rules.from') }}</label>
<date>
<datetime>
<input type="text" name="starts_from" class="control" value="{{ old('starts_from') ?: $cartRule->starts_from }}"/>
</date>
</datetime>
</div>
<div class="control-group date">
<label for="ends_till">{{ __('admin::app.promotions.cart-rules.to') }}</label>
<date>
<datetime>
<input type="text" name="ends_till" class="control" value="{{ old('ends_till') ?: $cartRule->ends_till }}"/>
</date>
</datetime>
</div>
<div class="control-group">

View File

@ -344,14 +344,11 @@
</tr>
@endif
@php ($taxRates = Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($order, true))
@foreach ($taxRates as $taxRate => $baseTaxAmount)
<tr {{ $loop->last ? 'class=border' : ''}}>
<td id="taxrate-{{ core()->taxRateAsIdentifier($taxRate) }}">{{ __('admin::app.sales.orders.tax') }} {{ $taxRate }} %</td>
<tr class="border">
<td>{{ __('admin::app.sales.orders.tax') }}</td>
<td>-</td>
<td id="basetaxamount-{{ core()->taxRateAsIdentifier($taxRate) }}">{{ core()->formatBasePrice($baseTaxAmount) }}</td>
<td>{{ core()->formatBasePrice($order->base_tax_amount) }}</td>
</tr>
@endforeach
<tr class="bold">
<td>{{ __('admin::app.sales.orders.grand-total') }}</td>
@ -437,9 +434,8 @@
<tr>
<th>{{ __('admin::app.sales.shipments.id') }}</th>
<th>{{ __('admin::app.sales.shipments.date') }}</th>
<th>{{ __('admin::app.sales.shipments.order-id') }}</th>
<th>{{ __('admin::app.sales.shipments.order-date') }}</th>
<th>{{ __('admin::app.sales.shipments.customer-name') }}</th>
<th>{{ __('admin::app.sales.shipments.carrier-title') }}</th>
<th>{{ __('admin::app.sales.shipments.tracking-number') }}</th>
<th>{{ __('admin::app.sales.shipments.total-qty') }}</th>
<th>{{ __('admin::app.sales.shipments.action') }}</th>
</tr>
@ -451,9 +447,8 @@
<tr>
<td>#{{ $shipment->id }}</td>
<td>{{ $shipment->created_at }}</td>
<td>#{{ $shipment->order->id }}</td>
<td>{{ $shipment->order->created_at }}</td>
<td>{{ $shipment->address->name }}</td>
<td>{{ $shipment->carrier_title }}</td>
<td>{{ $shipment->track_number }}</td>
<td>{{ $shipment->total_qty }}</td>
<td class="action">
<a href="{{ route('admin.sales.shipments.view', $shipment->id) }}">

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIsComparableColumnInAttributesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('attributes', function (Blueprint $table) {
$table->boolean('is_comparable')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('attributes', function (Blueprint $table) {
$table->dropColumn('is_comparable');
});
}
}

View File

@ -17,54 +17,78 @@ class AttributeTableSeeder extends Seeder
$now = Carbon::now();
DB::table('attributes')->insert([
['id' => '1','code' => 'sku','admin_name' => 'SKU','type' => 'text','validation' => NULL,'position' => '1','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '1','code' => 'sku','admin_name' => 'SKU','type' => 'text','validation' => NULL,'position' => '1','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '2','code' => 'name','admin_name' => 'Name','type' => 'text','validation' => NULL,'position' => '2','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '1'],
['id' => '3','code' => 'url_key','admin_name' => 'URL Key','type' => 'text','validation' => NULL,'position' => '3','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '4','code' => 'tax_category_id','admin_name' => 'Tax Category','type' => 'select','validation' => NULL,'position' => '4','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '5','code' => 'new','admin_name' => 'New','type' => 'boolean','validation' => NULL,'position' => '5','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '6','code' => 'featured','admin_name' => 'Featured','type' => 'boolean','validation' => NULL,'position' => '6','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '7','code' => 'visible_individually','admin_name' => 'Visible Individually','type' => 'boolean','validation' => NULL,'position' => '7','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,
'use_in_flat' => '1','updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '7','code' => 'visible_individually','admin_name' => 'Visible Individually','type' => 'boolean','validation' => NULL,'position' => '7','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now, 'use_in_flat' => '1','updated_at' => $now, 'is_comparable' => '0'],
['id' => '8','code' => 'status','admin_name' => 'Status','type' => 'boolean','validation' => NULL,'position' => '8','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '9','code' => 'short_description','admin_name' => 'Short Description','type' => 'textarea','validation' => NULL,'position' => '9','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0',
'is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '10','code' => 'description','admin_name' => 'Description','type' => 'textarea','validation' => NULL,'position' => '10','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '11','code' => 'price','admin_name' => 'Price','type' => 'price','validation' => 'decimal','position' => '11','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '1'],
['id' => '10','code' => 'description','admin_name' => 'Description','type' => 'textarea','validation' => NULL,'position' => '10','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '1'],
['id' => '12','code' => 'cost','admin_name' => 'Cost','type' => 'price','validation' => 'decimal','position' => '12','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '13','code' => 'special_price','admin_name' => 'Special Price','type' => 'price','validation' => 'decimal','position' => '13','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '14','code' => 'special_price_from','admin_name' => 'Special Price From','type' => 'date','validation' => NULL,'position' => '14','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '13','code' => 'special_price','admin_name' => 'Special Price','type' => 'price','validation' => 'decimal','position' => '13','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '14','code' => 'special_price_from','admin_name' => 'Special Price From','type' => 'date','validation' => NULL,'position' => '14','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '15','code' => 'special_price_to','admin_name' => 'Special Price To','type' => 'date','validation' => NULL,'position' => '15','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0',
'use_in_flat' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '16','code' => 'meta_title','admin_name' => 'Meta Title','type' => 'textarea','validation' => NULL,'position' => '16','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '17','code' => 'meta_keywords','admin_name' => 'Meta Keywords','type' => 'textarea','validation' => NULL,'position' => '17','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '18','code' => 'meta_description','admin_name' => 'Meta Description','type' => 'textarea','validation' => NULL,'position' => '18','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '18','code' => 'meta_description','admin_name' => 'Meta Description','type' => 'textarea','validation' => NULL,'position' => '18','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '19','code' => 'width','admin_name' => 'Width','type' => 'text','validation' => 'decimal','position' => '19','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '20','code' => 'height','admin_name' => 'Height','type' => 'text','validation' => 'decimal','position' => '20','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '21','code' => 'depth','admin_name' => 'Depth','type' => 'text','validation' => 'decimal','position' => '21','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '22','code' => 'weight','admin_name' => 'Weight','type' => 'text','validation' => 'decimal','position' => '22','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '23','code' => 'color','admin_name' => 'Color','type' => 'select','validation' => NULL,'position' => '23','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '24','code' => 'size','admin_name' => 'Size','type' => 'select','validation' => NULL,'position' => '24','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '25','code' => 'brand','admin_name' => 'Brand','type' => 'select','validation' => NULL,'position' => '25','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '1',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
['id' => '26','code' => 'guest_checkout','admin_name' => 'Guest Checkout','type' => 'boolean','validation' => NULL,'position' => '8','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now, 'is_comparable' => '0'],
]);

View File

@ -9,7 +9,7 @@ class Attribute extends TranslatableModel implements AttributeContract
{
public $translatedAttributes = ['name'];
protected $fillable = ['code', 'admin_name', 'type', 'position', 'is_required', 'is_unique', 'validation', 'value_per_locale', 'value_per_channel', 'is_filterable', 'is_configurable', 'is_visible_on_front', 'is_user_defined', 'swatch_type', 'use_in_flat'];
protected $fillable = ['code', 'admin_name', 'type', 'position', 'is_required', 'is_unique', 'validation', 'value_per_locale', 'value_per_channel', 'is_filterable', 'is_configurable', 'is_visible_on_front', 'is_user_defined', 'swatch_type', 'use_in_flat', 'is_comparable'];
// protected $with = ['options'];

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ChangeColumnTypeInCartRulesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('cart_rules', function (Blueprint $table) {
$table->dateTime('starts_from')->change();
$table->dateTime('ends_till')->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('cart_rules', function (Blueprint $table) {
$table->dateTime('starts_from')->change();
$table->dateTime('ends_till')->change();
});
}
}

View File

@ -8,6 +8,7 @@ use Webkul\CartRule\Repositories\CartRuleCouponRepository;
use Webkul\CartRule\Repositories\CartRuleCouponUsageRepository;
use Webkul\CartRule\Repositories\CartRuleCustomerRepository;
use Webkul\Customer\Repositories\CustomerGroupRepository;
use Webkul\Checkout\Models\CartItem;
use Webkul\Rule\Helpers\Validator;
use Webkul\Checkout\Facades\Cart;
@ -63,12 +64,13 @@ class CartRule
/**
* Create a new helper instance.
*
* @param Webkul\CartRule\Repositories\CartRuleRepository $cartRuleRepository
* @param Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
* @param Webkul\CartRule\Repositories\CartRuleCouponUsageRepository $cartRuleCouponUsageRepository
* @param Webkul\CartRule\Repositories\CartRuleCustomerRepository $cartRuleCustomerRepository
* @param Webkul\Customer\Repositories\CustomerGroupRepository $customerGroupRepository
* @param Webkul\Rule\Helpers\Validator $validator
* @param Webkul\CartRule\Repositories\CartRuleRepository $cartRuleRepository
* @param Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
* @param Webkul\CartRule\Repositories\CartRuleCouponUsageRepository $cartRuleCouponUsageRepository
* @param Webkul\CartRule\Repositories\CartRuleCustomerRepository $cartRuleCustomerRepository
* @param Webkul\Customer\Repositories\CustomerGroupRepository $customerGroupRepository
* @param Webkul\Rule\Helpers\Validator $validator
*
* @return void
*/
public function __construct(
@ -101,16 +103,22 @@ class CartRule
public function collect()
{
$cart = Cart::getCart();
$appliedCartRuleIds = [];
$this->calculateCartItemTotals($cart->items()->get());
foreach ($cart->items()->get() as $item) {
$this->process($item);
$itemCartRuleIds = $this->process($item);
$appliedCartRuleIds = array_merge($appliedCartRuleIds, $itemCartRuleIds);
if ($item->children()->count() && $item->product->getTypeInstance()->isChildrenCalculated())
$this->devideDiscount($item);
$this->divideDiscount($item);
}
$cart->applied_cart_rule_ids = implode(',', array_unique($appliedCartRuleIds, SORT_REGULAR));
$cart->save();
$cart->refresh();
$this->processShippingDiscount($cart);
$this->processFreeShippingDiscount($cart);
@ -139,18 +147,20 @@ class CartRule
$customerGroupId = $customerGuestGroup->id;
}
$cartRules = $this->cartRuleRepository->scopeQuery(function($query) use ($customerGroupId) {
$cartRules = $this->cartRuleRepository->scopeQuery(function ($query) use ($customerGroupId) {
return $query->leftJoin('cart_rule_customer_groups', 'cart_rules.id', '=', 'cart_rule_customer_groups.cart_rule_id')
->leftJoin('cart_rule_channels', 'cart_rules.id', '=', 'cart_rule_channels.cart_rule_id')
->where('cart_rule_customer_groups.customer_group_id', $customerGroupId)
->where('cart_rule_channels.channel_id', core()->getCurrentChannel()->id)
->where(function ($query1) {
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))->orWhereNull('cart_rules.starts_from');
})
->where(function ($query2) {
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))->orWhereNull('cart_rules.ends_till');
})
->orderBy('sort_order', 'asc');
->leftJoin('cart_rule_channels', 'cart_rules.id', '=', 'cart_rule_channels.cart_rule_id')
->where('cart_rule_customer_groups.customer_group_id', $customerGroupId)
->where('cart_rule_channels.channel_id', core()->getCurrentChannel()->id)
->where(function ($query1) {
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))
->orWhereNull('cart_rules.starts_from');
})
->where(function ($query2) {
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))
->orWhereNull('cart_rules.ends_till');
})
->orderBy('sort_order', 'asc');
})->findWhere(['status' => 1]);
return $cartRules;
@ -160,31 +170,34 @@ class CartRule
* Check if cart rule can be applied
*
* @param CartRule $rule
*
* @return boolean
*/
public function canProcessRule($rule)
public function canProcessRule($rule): bool
{
$cart = Cart::getCart();
if ($rule->coupon_type) {
if (strlen($cart->coupon_code)) {
$coupon = $this->cartRuleCouponRepository->findOneWhere([
'cart_rule_id' => $rule->id,
'code' => $cart->coupon_code,
]);
'cart_rule_id' => $rule->id,
'code' => $cart->coupon_code,
]);
if ($coupon) {
if ($coupon->usage_limit && $coupon->times_used >= $coupon->usage_limit)
if ($coupon->usage_limit && $coupon->times_used >= $coupon->usage_limit) {
return false;
}
if ($cart->customer_id && $coupon->usage_per_customer) {
$couponUsage = $this->cartRuleCouponUsageRepository->findOneWhere([
'cart_rule_coupon_id' => $coupon->id,
'customer_id' => $cart->customer_id
]);
'cart_rule_coupon_id' => $coupon->id,
'customer_id' => $cart->customer_id,
]);
if ($couponUsage && $couponUsage->times_used >= $coupon->usage_per_customer)
if ($couponUsage && $couponUsage->times_used >= $coupon->usage_per_customer) {
return false;
}
}
} else {
return false;
@ -196,9 +209,9 @@ class CartRule
if ($rule->usage_per_customer) {
$ruleCustomer = $this->cartRuleCustomerRepository->findOneWhere([
'cart_rule_id' => $rule->id,
'customer_id' => $cart->customer_id,
]);
'cart_rule_id' => $rule->id,
'customer_id' => $cart->customer_id,
]);
if ($ruleCustomer && $ruleCustomer->times_used >= $rule->usage_per_customer)
return false;
@ -210,19 +223,16 @@ class CartRule
/**
* Cart item discount calculation process
*
* @param CartItem $item
* @return void
* @param \Webkul\Checkout\Models\CartItem $item
*
* @return array
*/
public function process($item)
public function process(CartItem $item): array
{
$item->discount_percent = 0;
$item->discount_amount = 0;
$item->base_discount_amount = 0;
$cart = $item->cart;
$cart->applied_cart_rule_ids = null;
$appliedRuleIds = [];
foreach ($this->getCartRules() as $rule) {
@ -279,8 +289,9 @@ class CartRule
break;
case 'buy_x_get_y':
if (! $rule->discount_step || $rule->discount_amount > $rule->discount_step)
if (! $rule->discount_step || $rule->discount_amount > $rule->discount_step) {
break;
}
$buyAndDiscountQty = $rule->discount_step + $rule->discount_amount;
@ -290,8 +301,9 @@ class CartRule
$discountQty = $qtyPeriod * $rule->discount_amount;
if ($freeQty > $rule->discount_step)
if ($freeQty > $rule->discount_step) {
$discountQty += $freeQty - $rule->discount_step;
}
$discountAmount = $discountQty * $item->price;
@ -300,34 +312,28 @@ class CartRule
break;
}
$item->discount_amount = min($item->discount_amount + $discountAmount, $item->price * $quantity);
$item->base_discount_amount = min($item->base_discount_amount + $baseDiscountAmount, $item->base_price * $quantity);
$item->discount_amount = min($item->discount_amount + $discountAmount, $item->price * $quantity + $item->tax_amount);
$item->base_discount_amount = min($item->base_discount_amount + $baseDiscountAmount, $item->base_price * $quantity + $item->base_tax_amount);
$appliedRuleIds[$rule->id] = $rule->id;
if ($rule->end_other_rules)
if ($rule->end_other_rules) {
break;
}
}
$item->applied_cart_rule_ids = join(',', $appliedRuleIds);
$item->applied_cart_rule_ids = implode(',', $appliedRuleIds);
$item->save();
$cartAppliedCartRuleIds = array_merge(explode(',', $cart->applied_cart_rule_ids), $appliedRuleIds);
$cartAppliedCartRuleIds = array_filter($cartAppliedCartRuleIds);
$cartAppliedCartRuleIds = array_unique($cartAppliedCartRuleIds);
$cart->applied_cart_rule_ids = join(',', $cartAppliedCartRuleIds);
$cart->save();
return $appliedRuleIds;
}
/**
* Cart shipping discount calculation process
*
* @param Cart $cart
*
* @return void
*/
public function processShippingDiscount($cart)
@ -341,14 +347,17 @@ class CartRule
$appliedRuleIds = [];
foreach ($this->getCartRules() as $rule) {
if (! $this->canProcessRule($rule))
if (! $this->canProcessRule($rule)) {
continue;
}
if (! $this->validator->validate($rule, $cart))
if (! $this->validator->validate($rule, $cart)) {
continue;
}
if (! $rule || ! $rule->apply_to_shipping)
if (! $rule || ! $rule->apply_to_shipping) {
continue;
}
$discountAmount = $baseDiscountAmount = 0;
@ -373,16 +382,17 @@ class CartRule
$selectedShipping->discount_amount = min($selectedShipping->discount_amount + $discountAmount, $selectedShipping->price);
$selectedShipping->base_discount_amount = min(
$selectedShipping->base_discount_amount + $baseDiscountAmount,
$selectedShipping->base_price
);
$selectedShipping->base_discount_amount + $baseDiscountAmount,
$selectedShipping->base_price
);
$selectedShipping->save();
$appliedRuleIds[$rule->id] = $rule->id;
if ($rule->end_other_rules)
if ($rule->end_other_rules) {
break;
}
}
$selectedShipping->save();
@ -393,7 +403,7 @@ class CartRule
$cartAppliedCartRuleIds = array_unique($cartAppliedCartRuleIds);
$cart->applied_cart_rule_ids = join(',', $cartAppliedCartRuleIds);
$cart->applied_cart_rule_ids = implode(',', $cartAppliedCartRuleIds);
$cart->save();
@ -404,12 +414,14 @@ class CartRule
* Cart free shipping discount calculation process
*
* @param Cart $cart
*
* @return void
*/
public function processFreeShippingDiscount($cart)
{
if (! $selectedShipping = $cart->selected_shipping_rate)
if (! $selectedShipping = $cart->selected_shipping_rate) {
return;
}
$selectedShipping->discount_amount = 0;
@ -418,14 +430,17 @@ class CartRule
$appliedRuleIds = [];
foreach ($this->getCartRules() as $rule) {
if (! $this->canProcessRule($rule))
if (! $this->canProcessRule($rule)) {
continue;
}
if (! $this->validator->validate($rule, $cart))
if (! $this->validator->validate($rule, $cart)) {
continue;
}
if (! $rule || ! $rule->free_shipping)
if (! $rule || ! $rule->free_shipping) {
continue;
}
$selectedShipping->price = 0;
@ -454,6 +469,7 @@ class CartRule
* Calculate cart item totals for each rule
*
* @param mixed $items
*
* @return Validator
*/
public function calculateCartItemTotals($items)
@ -475,7 +491,7 @@ class CartRule
$this->itemTotals[$rule->id] = [
'base_total_price' => $totalBasePrice,
'total_items' => $validCount,
'total_items' => $validCount,
];
}
}
@ -490,29 +506,33 @@ class CartRule
{
$cart = Cart::getCart();
if (! $cart->coupon_code)
if (! $cart->coupon_code) {
return;
}
$coupon = $this->cartRuleCouponRepository->findOneByField('code', $cart->coupon_code);
if (! $coupon || ! in_array($coupon->cart_rule_id, explode(',', $cart->applied_cart_rule_ids)))
if (! $coupon || ! in_array($coupon->cart_rule_id, explode(',', $cart->applied_cart_rule_ids))) {
Cart::removeCouponCode();
}
}
/**
* Devide discount amount to children
* Divide discount amount to children
*
* @param CartItem $item
*
* @return void
*/
protected function devideDiscount($item)
protected function divideDiscount($item)
{
foreach ($item->children as $child) {
$ratio = $item->base_total != 0 ? $child->base_total / $item->base_total : 0;
foreach (['discount_amount', 'base_discount_amount'] as $column) {
if (! $item->{$column})
if (! $item->{$column}) {
continue;
}
$child->{$column} = round(($item->{$column} * $ratio), 4);
@ -520,4 +540,4 @@ class CartRule
}
}
}
}
}

View File

@ -11,7 +11,30 @@ use Webkul\Customer\Models\CustomerGroupProxy;
// class CartRule extends TranslatableModel implements CartRuleContract
class CartRule extends Model implements CartRuleContract
{
protected $fillable = ['name', 'description', 'starts_from', 'ends_till', 'status', 'coupon_type', 'use_auto_generation', 'usage_per_customer', 'uses_per_coupon', 'times_used', 'condition_type', 'conditions', 'actions', 'end_other_rules', 'uses_attribute_conditions', 'action_type', 'discount_amount', 'discount_quantity', 'discount_step', 'apply_to_shipping', 'free_shipping', 'sort_order'];
protected $fillable = [
'name',
'description',
'starts_from',
'ends_till',
'status',
'coupon_type',
'use_auto_generation',
'usage_per_customer',
'uses_per_coupon',
'times_used',
'condition_type',
'conditions',
'actions',
'end_other_rules',
'uses_attribute_conditions',
'action_type',
'discount_amount',
'discount_quantity',
'discount_step',
'apply_to_shipping',
'free_shipping',
'sort_order',
];
protected $casts = [
'conditions' => 'array',

View File

@ -212,7 +212,7 @@ class Cart
'items_count' => 1,
];
//Authentication details
// Fill in the customer data, as far as possible:
if ($this->getCurrentCustomer()->check()) {
$cartData['customer_id'] = $this->getCurrentCustomer()->user()->id;
$cartData['is_guest'] = 0;
@ -678,7 +678,7 @@ class Cart
$cart->tax_total = Tax::getTaxTotal($cart, false);
$cart->base_tax_total = Tax::getTaxTotal($cart, true);
$cart->grand_total = $cart->sub_total + $cart->tax_total + $cart->discount_amount;
$cart->grand_total = $cart->sub_total + $cart->tax_total - $cart->discount_amount;
$cart->base_grand_total = $cart->base_sub_total + $cart->base_tax_total - $cart->base_discount_amount;
if ($shipping = $cart->selected_shipping_rate) {

View File

@ -9,7 +9,21 @@ class CartAddress extends Model implements CartAddressContract
{
protected $table = 'cart_address';
protected $fillable = ['first_name', 'last_name', 'email', 'address1', 'city', 'state', 'postcode', 'country', 'phone', 'address_type', 'cart_id'];
protected $fillable = [
'first_name',
'last_name',
'email',
'company_name',
'vat_id',
'address1',
'city',
'state',
'postcode',
'country',
'phone',
'address_type',
'cart_id',
];
/**
* Get the shipping rates for the cart address.

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class PropagateCompanyName extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('cart_address', function (Blueprint $table) {
$table->string('company_name')->nullable()->after('email');
$table->string('vat_id')->nullable()->after('company_name');
});
Schema::table('order_address', function (Blueprint $table) {
$table->string('company_name')->nullable()->after('email');
$table->string('vat_id')->nullable()->after('company_name');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('cart_address', function (Blueprint $table) {
$table->dropColumn('company_name');
$table->dropColumn('vat_id');
});
Schema::table('order_address', function (Blueprint $table) {
$table->dropColumn('company_name');
$table->dropColumn('vat_id');
});
}
}

View File

@ -2,10 +2,17 @@
namespace Webkul\Product\Helpers;
use Webkul\Attribute\Models\Attribute;
use Webkul\Attribute\Models\AttributeOption;
use Webkul\Product\Repositories\ProductRepository as Product;
use Webkul\Attribute\Repositories\AttributeFamilyRepository as AttributeFamily;
use Illuminate\Support\Str;
/**
* Class GenerateProduct
*
* @package Webkul\Product\Helpers
*/
class GenerateProduct
{
/**
@ -28,18 +35,50 @@ class GenerateProduct
$this->product = $product;
$this->types = [
'text', 'textarea', 'boolean', 'select', 'multiselect', 'datetime', 'date', 'price', 'image', 'file', 'checkbox'
'text',
'textarea',
'boolean',
'select',
'multiselect',
'datetime',
'date',
'price',
'image',
'file',
'checkbox',
];
$this->attributeFamily = $attributeFamily;
}
/**
* This brand option needs to be available so that the generated product
* can be linked to the order_brands table after checkout.
*/
public function generateDemoBrand()
{
$brand = Attribute::where(['code' => 'brand'])->first();
if (! AttributeOption::where(['attribute_id' => $brand->id])->exists()) {
AttributeOption::create([
'admin_name' => 'Webkul Demo Brand (c) 2020',
'attribute_id' => $brand->id,
]);
}
}
/**
* @return mixed
*/
public function create()
{
$attributes = $this->getDefaultFamilyAttributes();
$attributeFamily = $this->attributeFamily->findWhere([
'code' => 'default'
'code' => 'default',
]);
$sku = Str::random(10);
@ -59,7 +98,11 @@ class GenerateProduct
foreach ($attributes as $attribute) {
if ($attribute->type == 'text') {
if ($attribute->code == 'width' || $attribute->code == 'height' || $attribute->code == 'depth' || $attribute->code == 'weight') {
if ($attribute->code == 'width'
|| $attribute->code == 'height'
|| $attribute->code == 'depth'
|| $attribute->code == 'weight'
) {
$data[$attribute->code] = $faker->randomNumber(3);
} else if ($attribute->code == 'url_key') {
$data[$attribute->code] = strtolower($sku);
@ -72,7 +115,7 @@ class GenerateProduct
$data[$attribute->code] = $faker->text;
if ($attribute->code == 'description' || $attribute->code == 'short_description') {
$data[$attribute->code] = '<p>'. $data[$attribute->code] . '</p>';
$data[$attribute->code] = '<p>' . $data[$attribute->code] . '</p>';
}
} else if ($attribute->type == 'boolean') {
$data[$attribute->code] = $faker->boolean;
@ -117,7 +160,7 @@ class GenerateProduct
} else if ($attribute->code == 'checkbox') {
$options = $attribute->options;
if ($options->count()) {
if ($options->count()) {
$option = $options->first()->id;
$optionArray = [];
@ -135,20 +178,23 @@ class GenerateProduct
$data['locale'] = core()->getCurrentLocale()->code;
$brand = Attribute::where(['code' => 'brand'])->first();
$data['brand'] = AttributeOption::where(['attribute_id' => $brand->id])->first()->id ?? '';
$data['channel'] = $channel->code;
$data['channels'] = [
0 => $channel->id
0 => $channel->id,
];
$inventorySource = $channel->inventory_sources[0];
$data['inventories'] = [
$inventorySource->id => 10
$inventorySource->id => 10,
];
$data['categories'] = [
0 => $channel->root_category->id
0 => $channel->root_category->id,
];
$updated = $this->product->update($data, $product->id);
@ -159,7 +205,7 @@ class GenerateProduct
public function getDefaultFamilyAttributes()
{
$attributeFamily = $this->attributeFamily->findWhere([
'code' => 'default'
'code' => 'default',
]);
$attributes = collect();

View File

@ -11,6 +11,24 @@ class OrderAddress extends Model implements OrderAddressContract
protected $guarded = ['id', 'created_at', 'updated_at'];
protected $fillable = [
'first_name',
'last_name',
'email',
'company_name',
'vat_id',
'address1',
'address2',
'city',
'state',
'postcode',
'country',
'phone',
'address_type',
'cart_id',
'customer_id',
];
/**
* Get of the customer fullname.
*/

View File

@ -17,7 +17,7 @@
"laravel-mix-merge-manifest": "^0.1.2",
"sass": "^1.24.4",
"sass-loader": "^8.0.0",
"vue": "^2.6.10",
"vue": "^2.6.11",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {

File diff suppressed because one or more lines are too long

View File

@ -39,3 +39,9 @@
*
* Date: 2019-05-01T21:04Z
*/
/**
* vue-class-component v7.0.1
* (c) 2015-present Evan You
* @license MIT
*/

View File

@ -1,4 +1,4 @@
{
"/js/shop.js": "/js/shop.js?id=6d8ea335fbfa47e80e72",
"/js/shop.js": "/js/shop.js?id=6bb928c2e527b045a56b",
"/css/shop.css": "/css/shop.css?id=ccf417b825955d8bd301"
}

View File

@ -1,12 +1,12 @@
import $ from 'jquery';
import Vue from 'vue';
import VeeValidate from 'vee-validate';
import de from 'vee-validate/dist/locale/de';
import ar from 'vee-validate/dist/locale/ar';
import axios from 'axios';
import VueSlider from 'vue-slider-component';
import accounting from 'accounting';
import ImageSlider from './components/image-slider';
import { messages as localeMessages } from './lang/locales';
window.jQuery = window.$ = $;
window.Vue = Vue;
@ -17,7 +17,8 @@ require("ez-plus/src/jquery.ez-plus.js");
Vue.use(VeeValidate, {
dictionary: {
ar: { messages: localeMessages.ar }
ar: ar,
de: de,
},
events: 'input|change|blur',
});

View File

@ -1,28 +0,0 @@
export const messages = {
ar: {
required : (field) => 'حقل' + field + ' مطلوب',
alpha : (field) => field + ' يجب ان يحتوي على حروف فقط',
alpha_num : (field) => field + ' قد يحتوي فقط على حروف وارقام',
min : (field, length) => 'الحقل ' + field + ' يجب ان يحتوي على ' + length + ' حروف على الأقل',
numeric : (field) => field + ' يمكن ان يحتوي فقط على ارقام',
oneOf : (field) => 'الحقل ' + field + 'يجب ان يكون قيمة صحيحة',
regex : (field) => 'الحقل' + field+ ' غير صحيح',
required_if : (field) => 'حقل' + field + ' مطلوب',
size : (field, size) => field + ' يجب ان يكون اقل من ' + size + ' كيلوبايت',
min_value : (field, min) => 'قيمة الحقل' + field + ' يجب ان تكون اكبر من ' + min + ' او تساويها',
alpha_spaces : (field) => field + ' قد يحتوي فقط على حروف ومسافات',
between : (field, min, max) => 'قيمة ' +field+ ' يجب ان تكون ما بين ' + min + ' و ' + max,
confirmed : (field) => field + ' لا يماثل التأكيد',
digits : (field, length) => field + ' يجب ان تحتوي فقط على ارقام والا يزيد عددها عن ' + length + ' رقم',
dimensions : (field, width, height) => field + ' يجب ان تكون بمقاس ' + width + ' بكسل في ' + height + ' بكسل',
email : (field) => field + ' يجب ان يكون بريدا اليكتروني صحيح',
excluded : (field) => 'الحقل' + field +'غير صحيح',
ext : (field) =>'نوع مل'+ field + 'غير صحيح',
image : (field) => field + ' يجب ان تكون صورة',
integer : (field) => 'الحقل ' +field + ' يجب ان يكون عدداً صحيحاً',
length : (field, length) => 'حقل'+ field + ' يجب الا يزيد عن ' + length,
max_value : (field, min) => 'قيمة الحقل '+ field + ' يجب ان تكون اصغر من ' + min + ' او تساويها',
max : (field, length) => 'الحقل' + field + 'يجب ان يحتوي على ' + length + ' حروف على الأكثر',
mimes : (field) => 'نوع ملف' + field + 'غير صحيح'
}
}

View File

@ -7,4 +7,6 @@
</form>
@include('shop::products.wishlist')
@include('shop::products.compare')
</div>

View File

@ -0,0 +1,11 @@
{{-- @inject ('wishListHelper', 'Webkul\Customer\Helpers\Wishlist')
@auth('customer')
{!! view_render_event('bagisto.shop.products.wishlist.before') !!}
<a @if ($wishListHelper->getWishlistProduct($product)) class="add-to-wishlist already" @else class="add-to-wishlist" @endif href="{{ route('customer.wishlist.add', $product->product_id) }}" id="wishlist-changer">
<span class="icon wishlist-icon"></span>
</a>
{!! view_render_event('bagisto.shop.products.wishlist.after') !!}
@endauth --}}

View File

@ -22,8 +22,17 @@ class ThemeViewFinder extends FileViewFinder
if ($namespace != 'admin') {
$paths = $this->addThemeNamespacePaths($namespace);
// Find and return the view
return $this->findInPaths($view, $paths);
try {
return $this->findInPaths($view, $paths);
} catch(\Exception $e) {
if ($namespace != 'shop') {
if (strpos($view, 'shop.') !== false) {
$view = str_replace('shop.', 'shop.' . Themes::current()->code . '.', $view);
}
}
return $this->findInPaths($view, $paths);
}
} else {
return $this->findInPaths($view, $this->hints[$namespace]);
}
@ -43,7 +52,6 @@ class ThemeViewFinder extends FileViewFinder
$newPath = base_path() . '/' . $path;
$paths = Arr::prepend($paths, $newPath);
}
return $paths;
@ -80,6 +88,7 @@ class ThemeViewFinder extends FileViewFinder
public function setPaths($paths)
{
$this->paths = $paths;
$this->flush();
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{
"/js/velocity.js": "/js/velocity.js?id=5d429b3399bd1ffaefbc",
"/js/velocity.js": "/js/velocity.js?id=0acc6147ad60ac08da04",
"/css/velocity-admin.css": "/css/velocity-admin.css?id=612d35e452446366eef7",
"/css/velocity.css": "/css/velocity.css?id=249c3b3462d6a9013c20"
"/css/velocity.css": "/css/velocity.css?id=ceec6d6cde43e397bf26"
}

View File

@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCustomerCompareProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('velocity_customer_compare_products', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('product_flat_id');
$table->foreign('product_flat_id')
->references('id')
->on('product_flat')
->onUpdate('cascade')
->onDelete('cascade');
$table->unsignedInteger('customer_id');
$table->foreign('customer_id')
->references('id')
->on('customers')
->onUpdate('cascade')
->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('velocity_customer_compare_products');
}
}

View File

@ -2,11 +2,16 @@
namespace Webkul\Velocity\Http\Controllers\Shop;
use Illuminate\Http\Request;
use Cart;
use Webkul\Product\Helpers\ProductImage;
use Webkul\Velocity\Http\Shop\Controllers;
use Webkul\Checkout\Contracts\Cart as CartModel;
use Webkul\Product\Repositories\SearchRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Category\Repositories\CategoryRepository;
use Webkul\Velocity\Repositories\VelocityCustomerCompareProductRepository;
use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRepository;
/**
@ -24,6 +29,13 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
*/
protected $_config;
/**
* Webkul\Product\Helpers\ProductImage object
*
* @var ProductImage
*/
protected $productImageHelper;
/**
* SearchRepository object
*
@ -45,22 +57,47 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
*/
protected $velocityProductRepository;
/**
* CategoryRepository object of velocity package
*
* @var CategoryRepository
*/
protected $categoryRepository;
/**
* VelocityCustomerCompareProductRepository object of velocity package
*
* @var VelocityCustomerCompareProductRepository
*/
protected $velocityCompareProductsRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
* @param \Webkul\Product\Repositories\SearchRepository $searchRepository
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
* @param \Webkul\Category\Repositories\CategoryRepository $categoryRepository
* @param \Webkul\Velocity\Repositories\Product\ProductRepository $velocityProductRepository
* @param \Webkul\Velocity\Repositories\VelocityCustomerCompareProductRepository $velocityCompareProductsRepository
* @return void
*/
public function __construct(
ProductImage $productImageHelper,
SearchRepository $searchRepository,
ProductRepository $productRepository,
VelocityProductRepository $velocityProductRepository
CategoryRepository $categoryRepository,
VelocityProductRepository $velocityProductRepository,
VelocityCustomerCompareProductRepository $velocityCompareProductsRepository
) {
$this->_config = request('_config');
$this->searchRepository = $searchRepository;
$this->productRepository = $productRepository;
$this->productImageHelper = $productImageHelper;
$this->categoryRepository = $categoryRepository;
$this->velocityProductRepository = $velocityProductRepository;
$this->velocityCompareProductsRepository = $velocityCompareProductsRepository;
}
/**
@ -81,24 +118,23 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
if ($product) {
$productReviewHelper = app('Webkul\Product\Helpers\Review');
$productImageHelper = app('Webkul\Product\Helpers\ProductImage');
$galleryImages = $productImageHelper->getProductBaseImage($product);
$galleryImages = $this->productImageHelper->getProductBaseImage($product);
$response = [
'status' => true,
'status' => true,
'details' => [
'name' => $product->name,
'urlKey' => $product->url_key,
'priceHTML' => $product->getTypeInstance()->getPriceHtml(),
'totalReviews' => $productReviewHelper->getTotalReviews($product),
'rating' => ceil($productReviewHelper->getAverageRating($product)),
'image' => $galleryImages['small_image_url'],
'name' => $product->name,
'urlKey' => $product->url_key,
'image' => $galleryImages['small_image_url'],
'priceHTML' => $product->getTypeInstance()->getPriceHtml(),
'totalReviews' => $productReviewHelper->getTotalReviews($product),
'rating' => ceil($productReviewHelper->getAverageRating($product)),
]
];
} else {
$response = [
'status' => false,
'slug' => $slug,
'slug' => $slug,
];
}
@ -134,7 +170,7 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
break;
default:
$categoryDetails = app('Webkul\Category\Repositories\CategoryRepository')->findByPath($slug);
$categoryDetails = $this->categoryRepository->findByPath($slug);
if ($categoryDetails) {
$list = false;
@ -149,10 +185,10 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
}
$response = [
'status' => true,
'list' => $list,
'categoryDetails' => $categoryDetails,
'categoryProducts' => $customizedProducts,
'status' => true,
'list' => $list,
'categoryDetails' => $categoryDetails,
'categoryProducts' => $customizedProducts,
];
}
@ -167,25 +203,25 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
public function fetchCategories()
{
$formattedCategories = [];
$categories = app('Webkul\Category\Repositories\CategoryRepository')->getVisibleCategoryTree(core()->getCurrentChannel()->root_category_id);
$categories = $this->categoryRepository->getVisibleCategoryTree(core()->getCurrentChannel()->root_category_id);
foreach ($categories as $category) {
array_push($formattedCategories, $this->getCategoryFilteredData($category));
}
return [
'status' => true,
'categories' => $formattedCategories,
'status' => true,
'categories' => $formattedCategories,
];
}
public function fetchFancyCategoryDetails($slug)
{
$categoryDetails = app('Webkul\Category\Repositories\CategoryRepository')->findByPath($slug);
$categoryDetails = $this->categoryRepository->findByPath($slug);
if ($categoryDetails) {
$response = [
'status' => true,
'status' => true,
'categoryDetails' => $this->getCategoryFilteredData($categoryDetails)
];
}
@ -198,46 +234,47 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
private function getCategoryFilteredData($category)
{
$formattedChildCategory = [];
foreach ($category->children as $child) {
array_push($formattedChildCategory, $this->getCategoryFilteredData($child));
}
return [
'id' => $category->id,
'slug' => $category->slug,
'name' => $category->name,
'children' => $formattedChildCategory,
'category_icon_path' => $category->category_icon_path,
'id' => $category->id,
'slug' => $category->slug,
'name' => $category->name,
'children' => $formattedChildCategory,
'category_icon_path' => $category->category_icon_path,
];
}
private function formatProduct($product, $list = false)
{
$reviewHelper = app('Webkul\Product\Helpers\Review');
$productImageHelper = app('Webkul\Product\Helpers\ProductImage');
$totalReviews = $reviewHelper->getTotalReviews($product);
$avgRatings = ceil($reviewHelper->getAverageRating($product));
$galleryImages = $productImageHelper->getGalleryImages($product);
$productImage = $productImageHelper->getProductBaseImage($product)['medium_image_url'];
$galleryImages = $this->productImageHelper->getGalleryImages($product);
$productImage = $this->productImageHelper->getProductBaseImage($product)['medium_image_url'];
return [
'name' => $product->name,
'slug' => $product->url_key,
'image' => $productImage,
'description' => $product->description,
'shortDescription' => $product->short_description,
'galleryImages' => $galleryImages,
'priceHTML' => view('shop::products.price', ['product' => $product])->render(),
'totalReviews' => $totalReviews,
'avgRating' => $avgRatings,
'firstReviewText' => trans('velocity::app.products.be-first-review'),
'addToCartHtml' => view('shop::products.add-to-cart', [
'product' => $product,
'addWishlistClass' => !(isset($list) && $list) ? '' : '',
'addToCartBtnClass' => !(isset($list) && $list) ? $addToCartBtnClass ?? '' : ''
'avgRating' => $avgRatings,
'totalReviews' => $totalReviews,
'image' => $productImage,
'galleryImages' => $galleryImages,
'name' => $product->name,
'slug' => $product->url_key,
'description' => $product->description,
'shortDescription' => $product->short_description,
'firstReviewText' => trans('velocity::app.products.be-first-review'),
'priceHTML' => view('shop::products.price', ['product' => $product])->render(),
'addToCartHtml' => view('shop::products.add-to-cart', [
'product' => $product,
'showCompare' => true,
'addWishlistClass' => !(isset($list) && $list) ? '' : '',
'addToCartBtnClass' => !(isset($list) && $list) ? 'small-padding' : '',
])->render(),
];
}
@ -281,31 +318,164 @@ use Webkul\Velocity\Repositories\Product\ProductRepository as VelocityProductRep
}
$response = [
'status' => 'success',
'totalCartItems' => sizeof($items),
'addedItems' => array_slice($formattedItems, sizeof($formattedBeforeItems)),
'message' => trans('shop::app.checkout.cart.item.success'),
'status' => 'success',
'totalCartItems' => sizeof($items),
'message' => trans('shop::app.checkout.cart.item.success'),
'addedItems' => array_slice($formattedItems, sizeof($formattedBeforeItems)),
];
if ($customer = auth()->guard('customer')->user())
if ($customer = auth()->guard('customer')->user()) {
$this->wishlistRepository->deleteWhere(['product_id' => $id, 'customer_id' => $customer->id]);
}
if (request()->get('is_buy_now'))
if (request()->get('is_buy_now')) {
return redirect()->route('shop.checkout.onepage.index');
}
}
} catch(\Exception $exception) {
$product = $this->productRepository->find($id);
$response = [
'status' => 'false',
'message' => trans($exception->getMessage()),
'redirectionRoute' => route('shop.productOrCategory.index', $product->url_key),
'status' => 'false',
'message' => trans($exception->getMessage()),
'redirectionRoute' => route('shop.productOrCategory.index', $product->url_key),
];
}
return $response ?? [
'status' => 'error',
'message' => trans('velocity::app.error.something-went-wrong'),
'status' => 'error',
'message' => trans('velocity::app.error.something-went-wrong'),
];
}
/**
* function for customers to get products in comparison.
*
* @return Mixed
*/
public function getComparisonList(Request $request)
{
if (request()->get('data')) {
$productSlugs = null;
$productCollection = [];
if (auth()->guard('customer')->user()) {
$productCollection = $this->velocityCompareProductsRepository
->leftJoin(
'product_flat',
'velocity_customer_compare_products.product_flat_id',
'product_flat.id'
)
->where('customer_id', auth()->guard('customer')->user()->id)
->get()
->toArray();
foreach ($productCollection as $index => $customerCompare) {
$product = $this->productRepository->find($customerCompare['product_id']);
$formattedProduct = $this->formatProduct($product);
$productCollection[$index]['image'] = $formattedProduct['image'];
$productCollection[$index]['priceHTML'] = $formattedProduct['priceHTML'];
$productCollection[$index]['addToCartHtml'] = $formattedProduct['addToCartHtml'];
}
} else {
// for product details
if ($items = request()->get('items')) {
$productSlugs = explode('&', $items);
foreach ($productSlugs as $slug) {
$product = $this->productRepository->findBySlug($slug);
array_push($productCollection, $this->formatProduct($product));
}
}
}
$response = [
'status' => 'success',
'products' => $productCollection,
];
} else {
$response = view($this->_config['view']);
}
return $response;
}
/**
* function for customers to add product in comparison.
*
* @return json
*/
public function addCompareProduct()
{
$productId = request()->get('productId');
$customerId = auth()->guard('customer')->user()->id;
$compareProduct = $this->velocityCompareProductsRepository->findOneByField([
'customer_id' => $customerId,
'product_flat_id' => $productId,
]);
if (! $compareProduct) {
// insert new row
$this->velocityCompareProductsRepository->create([
'customer_id' => $customerId,
'product_flat_id' => $productId,
]);
return response()->json([
'status' => 'success',
'message' => trans('velocity::app.customer.compare.added'),
'label' => trans('velocity::app.shop.general.alert.success'),
], 201);
} else {
return response()->json([
'status' => 'success',
'label' => trans('velocity::app.shop.general.alert.success'),
'message' => trans('velocity::app.customer.compare.already_added'),
], 200);
}
}
/**
* function for customers to delete product in comparison.
*
* @return json
*/
public function deleteComparisonProduct()
{
// either delete all or individual
if (request()->get('productId') == 'all') {
// delete all
$customerId = auth()->guard('customer')->user()->id;
$this->velocityCompareProductsRepository->deleteWhere([
'customer_id' => auth()->guard('customer')->user()->id,
]);
} else {
// delete individual
$this->velocityCompareProductsRepository->deleteWhere([
'product_flat_id' => request()->get('productId'),
'customer_id' => auth()->guard('customer')->user()->id,
]);
// $comparedList = json_decode($customer->compared_product, true);
// $index = array_search($productId, $comparedList);
// if ($index > -1) {
// unset($comparedList[$index]);
// $this->velocityCustomerDataRepository->update([
// 'compared_product' => json_encode($comparedList),
// ], $customer->id);
// }
}
return [
'status' => 'success',
'message' => trans('velocity::app.customer.compare.removed'),
'label' => trans('velocity::app.shop.general.alert.success'),
];
}
}

View File

@ -16,5 +16,15 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function
Route::get('/fancy-category-details/{slug}', 'ShopController@fetchFancyCategoryDetails')->name('velocity.fancy.category.details');
Route::post('/cart/add', 'ShopController@addProductToCart')->name('velocity.cart.add.product');
Route::get('/comparison', 'ShopController@getComparisonList')
->name('velocity.product.compare')
->defaults('_config', [
'view' => 'shop::compare.index'
]);
Route::put('/comparison', 'ShopController@addCompareProduct')->name('customer.product.add.compare');
Route::delete('/comparison', 'ShopController@deleteComparisonProduct')->name('customer.product.delete.compare');
});
});

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Velocity\Models;
use Illuminate\Database\Eloquent\Model;
class VelocityCustomerCompareProduct extends Model
{
protected $guarded = [];
}

View File

@ -0,0 +1,18 @@
<?php
namespace Webkul\Velocity\Repositories;
use Webkul\Core\Eloquent\Repository;
class VelocityCustomerCompareProductRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Velocity\Models\VelocityCustomerCompareProduct';
}
}

View File

@ -82,7 +82,7 @@
}
})
.catch(error => {
console.log("something went wrong");
console.log(this.__('error.something-went-wrong'));
})
}
}

View File

@ -0,0 +1,68 @@
<template>
<a class="unset compare-icon text-right" @click="addProductToCompare">
<i class="material-icons">compare_arrows</i>
</a>
</template>
<script>
export default {
props: ['slug', 'customer', 'productId'],
data: function () {
return {}
},
methods: {
addProductToCompare: function () {
if (this.customer == "true") {
this.$http.put(
`${this.$root.baseUrl}/comparison`, {
productId: this.productId,
}
).then(response => {
window.showAlert(`alert-${response.data.status}`, response.data.label, response.data.message);
}).catch(error => {
window.showAlert(
'alert-danger',
this.__('shop.general.alert.error'),
this.__('error.something-went-wrong')
);
});
} else {
let updatedItems = [this.slug];
let existingItems = window.localStorage.getItem('compared_product');
if (existingItems) {
existingItems = JSON.parse(existingItems);
if (existingItems.indexOf(this.slug) == -1) {
updatedItems = existingItems.concat([this.slug]);
window.localStorage.setItem('compared_product', JSON.stringify(updatedItems));
window.showAlert(
`alert-success`,
this.__('shop.general.alert.success'),
`${this.__('customer.compare.added')}`
);
} else {
window.showAlert(
`alert-success`,
this.__('shop.general.alert.success'),
`${this.__('customer.compare.already_added')}`
);
}
} else {
window.localStorage.setItem('compared_product', JSON.stringify([this.slug]));
window.showAlert(
`alert-success`,
this.__('shop.general.alert.success'),
`${this.__('customer.compare.added')}`
);
}
}
}
}
}
</script>

View File

@ -114,7 +114,7 @@
try {
var output = render.call(this, this.$createElement)
} catch (exception) {
console.log("something went wrong");
console.log(this.__('error.something-went-wrong'));
}
this.$options.staticRenderFns = _staticRenderFns

View File

@ -11,9 +11,9 @@
:key="categoryIndex"
:id="`category-${category.id}`"
class="category-content cursor-pointer"
v-for="(category, categoryIndex) in slicedCategories"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="toggleSidebar(id, $event, 'mouseover')">
@mouseover="toggleSidebar(id, $event, 'mouseover')"
v-for="(category, categoryIndex) in slicedCategories">
<a
:class="`category unset ${(category.children.length > 0) ? 'fw6' : ''}`"
@ -28,7 +28,9 @@
v-if="category.category_icon_path"
:src="`${$root.baseUrl}/storage/${category.category_icon_path}`" />
</div>
<span class="category-title">{{ category['name'] }}</span>
<i
class="rango-arrow-right pr15 pull-right"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@ -41,18 +43,23 @@
class="sub-category-container"
v-if="category.children.length && category.children.length > 0">
<div :class="`sub-categories sub-category-${sidebarLevel+categoryIndex}`">
<div
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="remainBar(`sidebar-level-${sidebarLevel+categoryIndex}`)"
:class="`sub-categories sub-category-${sidebarLevel+categoryIndex} cursor-default`">
<nav
class="sidebar"
@mouseover="remainBar(`sidebar-level-${sidebarLevel+categoryIndex}`)"
:id="`sidebar-level-${sidebarLevel+categoryIndex}`">
:id="`sidebar-level-${sidebarLevel+categoryIndex}`"
@mouseover="remainBar(`sidebar-level-${sidebarLevel+categoryIndex}`)">
<ul type="none">
<li
:key="`${subCategoryIndex}-${categoryIndex}`"
v-for="(subCategory, subCategoryIndex) in category.children">
<a
:class="`category unset ${(subCategory.children.length > 0) ? 'fw6' : ''}`"
:class="`category sub-category unset ${(subCategory.children.length > 0) ? 'fw6' : ''}`"
:href="`${$root.baseUrl}/${category.slug}/${subCategory.slug}`">
<div
@ -143,7 +150,7 @@
slicedCategories['parentSlug'] = this.parentSlug;
this.slicedCategories = slicedCategories;
}
},
}
}
</script>

View File

@ -0,0 +1,53 @@
<template>
<div :class="`stars mr5 fs${size ? size : '16'} ${pushClass ? pushClass : ''}`">
<input
v-if="editable"
type="number"
:value="showFilled"
name="rating"
class="hidden" />
<i
:class="`material-icons ${editable ? 'cursor-pointer' : ''}`"
v-for="(rating, index) in parseInt((showFilled != 'undefined') ? showFilled : 3)"
:key="`${index}${Math.random()}`"
@click="updateRating(index + 1)">
star
</i>
<template v-if="!hideBlank">
<i
:class="`material-icons ${editable ? 'cursor-pointer' : ''}`"
v-for="(blankStar, index) in (5 - ((showFilled != 'undefined') ? showFilled : 3))"
:key="`${index}${Math.random()}`"
@click="updateRating(showFilled + index + 1)">
star_border
</i>
</template>
</div>
</template>
<script type="text/javascript">
export default {
props: [
'size',
'ratings',
'editable',
'hideBlank',
'pushClass',
],
data: function () {
return {
showFilled: this.ratings,
}
},
methods: {
updateRating: function (index) {
index = Math.abs(index);
this.editable ? this.showFilled = index : '';
}
},
}
</script>

View File

@ -33,6 +33,7 @@ window.Carousel = VueCarousel;
Vue.component("vue-slider", require("vue-slider-component"));
Vue.component('modal-component', require('./UI/components/modal'));
Vue.component("add-to-cart", require("./UI/components/add-to-cart"));
Vue.component('star-ratings', require('./UI/components/star-rating'));
Vue.component('quantity-btn', require('./UI/components/quantity-btn'));
Vue.component('sidebar-component', require('./UI/components/sidebar'));
Vue.component("product-card", require("./UI/components/product-card"));
@ -41,6 +42,7 @@ Vue.component('carousel-component', require('./UI/components/carousel'));
Vue.component('child-sidebar', require('./UI/components/child-sidebar'));
Vue.component('card-list-header', require('./UI/components/card-header'));
Vue.component('magnify-image', require('./UI/components/image-magnifier'));
Vue.component('compare-component', require('./UI/components/product-compare'));
Vue.component('responsive-sidebar', require('./UI/components/responsive-sidebar'));
Vue.component('product-quick-view', require('./UI/components/product-quick-view'));
Vue.component('product-quick-view-btn', require('./UI/components/product-quick-view-btn'));
@ -50,6 +52,7 @@ window.eventBus = new Vue();
$(document).ready(function () {
// define a mixin object
Vue.mixin(require('./UI/components/trans'));
Vue.mixin({
data: function () {
return {
@ -67,6 +70,12 @@ $(document).ready(function () {
route ? window.location.href = route : '';
},
debounceToggleSidebar: function (id, {target}, type) {
// setTimeout(() => {
this.toggleSidebar(id, target, type);
// }, 500);
},
toggleSidebar: function (id, {target}, type) {
if (
Array.from(target.classList)[0] == "main-category"
@ -81,11 +90,11 @@ $(document).ready(function () {
}
}
} else if (
Array.from(target.classList)[0] == "category"
|| Array.from(target.classList)[0] == "category-icon"
|| Array.from(target.classList)[0] == "category-title"
|| Array.from(target.classList)[0] == "category-content"
|| Array.from(target.classList)[0] == "rango-arrow-right"
Array.from(target.classList)[0] == "category"
|| Array.from(target.classList)[0] == "category-icon"
|| Array.from(target.classList)[0] == "category-title"
|| Array.from(target.classList)[0] == "category-content"
|| Array.from(target.classList)[0] == "rango-arrow-right"
) {
let parentItem = target.closest('li');
if (target.id || parentItem.id.match('category-')) {
@ -154,6 +163,21 @@ $(document).ready(function () {
return false
}
},
getDynamicHTML: function (input) {
const { render, staticRenderFns } = Vue.compile(input);
const _staticRenderFns = this.$options.staticRenderFns = staticRenderFns;
try {
var output = render.call(this, this.$createElement)
} catch (exception) {
console.log(this.__('error.something-went-wrong'));
}
this.$options.staticRenderFns = _staticRenderFns
return output;
}
}
});
@ -265,6 +289,7 @@ $(document).ready(function () {
this.$http.get(`${this.baseUrl}/categories`)
.then(response => {
this.sharedRootCategories = response.data.categories;
$(`<style type='text/css'> .sub-categories{ min-height:${response.data.categories.length * 30}px;} </style>`).appendTo("head");
})
.catch(error => {
console.log('failed to load categories');
@ -280,7 +305,7 @@ $(document).ready(function () {
}
})
});
}
},
}
});

View File

@ -510,6 +510,18 @@ header {
}
}
}
~ .compare-btn {
height: 50px;
float: right;
font-size: 18px;
font-weight: 600;
padding: 10px 16px 6px 16px;
i {
vertical-align: middle;
}
}
}
.dropdown-menu-large {

View File

@ -255,6 +255,8 @@
}
.card-body {
cursor: default;
> div:last-child {
margin-top: 10px;
}
@ -274,17 +276,6 @@
}
}
.wishlist-icon {
height: 38px;
display: table;
text-align: right;
> i {
display: table-cell;
vertical-align: middle;
}
}
.add-to-cart-btn {
width: 100%;
position: relative;
@ -298,11 +289,24 @@
}
}
~ .wishlist-icon {
~ a {
right: 0;
margin: 0;
padding: 0;
height: 38px;
display: table;
cursor: pointer;
text-align: right;
position: absolute;
&.compare-icon {
right: 27px;
}
> i {
display: table-cell;
vertical-align: middle;
}
}
}
}
@ -708,9 +712,7 @@
.customer-sidebar {
border-right: 1px solid $border-general;
}
.customer-sidebar {
.account-details {
text-align: center;
padding: 25px 20px;
@ -775,6 +777,10 @@
&.downloadables::before {
content: "\e926";
}
&.compare::before {
content: "\e93b";
}
}
}
@ -1494,7 +1500,7 @@
span:nth-child(1),
.special-price,
.price-from > span:not(:nth-child(2)) {
font-size: 20px;
font-size: 20px !important;
font-weight: 600;
}
@ -2196,6 +2202,16 @@
@extend .small-padding;
}
}
.VueCarousel-slide {
cursor: default;
}
#new-products-carousel {
.compare-icon {
display: none;
}
}
}
.vue-slider {
@ -2205,3 +2221,56 @@
.profile-update-form {
width: 800px;
}
.compare-products {
.col,
.col-2 {
padding-left: 0;
max-width: 20%;
}
.image-wrapper {
width: 100%;
}
.stars {
i {
font-size: 16px;
}
}
.action {
position: relative;
.close-btn {
right: 0;
top: 6px;
position: absolute;
display: inline-block;
&:hover {
font-weight: 600;
}
}
.compare-icon {
display: none;
}
}
.product-price {
span {
font-size: 24px !important
}
}
.material-icons {
&.cross {
top: 5px;
right: 20px;
cursor: pointer;
position: absolute;
}
}
}

View File

@ -643,6 +643,7 @@ body::after {
}
}
.compare-icon,
.wishlist-icon {
height: 38px;
display: table;

View File

@ -159,26 +159,38 @@
display: none;
}
.cart-wish-wrap {
.add-to-cart-btn {
padding: 0;
display: table;
.add-to-cart-btn {
padding: 0;
display: table;
.btn-add-to-cart {
.small-padding {
&.btn-add-to-cart {
padding: 3px 14px !important;
}
.btn-add-to-cart {
.small-padding {
&.btn-add-to-cart {
padding: 3px 14px !important;
}
}
}
.wishlist-icon {
padding: 0;
max-width: 25px;
~ a {
position: relative;
&.compare-icon {
right: 0;
}
&.wishlist-icon {
padding: 0;
left: 10px;
max-width: 25px;
}
}
}
}
#quick-view-btn-container {
display: none;
}
}
}
@ -485,6 +497,10 @@
padding: 0px;
position: relative;
margin-bottom: 20px;
.vc-small-product-image {
width: 100%;
}
}
.right {
@ -868,4 +884,18 @@
margin-left: 0;
}
}
.compare-products {
padding: 0 !important;
.col,
.col-2 {
max-width: unset;
}
}
.compare-icon,
.wishlist-icon {
margin-left: 0;
}
}

View File

@ -6,6 +6,7 @@
.magnifier {
> img {
max-width: 100%;
min-height: 450px;
max-height: 530px;
}
@ -219,9 +220,11 @@
}
}
.compare-icon,
.wishlist-icon {
height: 46px;
display: table;
cursor: pointer;
padding-left: 10px;
i {

View File

@ -124,7 +124,7 @@
margin-top: 10px;
}
.mt15 {
margin-top: 15px;
margin-top: 15px !important;
}
.mr5 {
margin-right: 5px;
@ -876,4 +876,16 @@ button[disabled] {
z-index: 5000;
position: fixed;
background: rgba(255, 255, 255, 0.9);
}
.compare-icon,
.wishlist-icon {
height: 38px;
display: table;
margin-left: 10px;
i {
display: table-cell;
vertical-align: middle;
}
}

View File

@ -8,6 +8,14 @@ return [
],
'customer' => [
'compare' => [
'text' => 'قارن',
'compare_similar_items' => 'مقارنة العناصر المماثلة',
'added' => 'تمت إضافة العنصر بنجاح لمقارنة القائمة',
'removed' => 'تمت إزالة العنصر بنجاح من قائمة المقارنة',
'already_added' => 'تمت إضافة العنصر بالفعل لمقارنة القائمة',
'empty-text' => "ليس لديك أي عناصر في قائمة المقارنة الخاصة بك",
],
'login-form' => [
'sign-up' => 'سجل',
'new-customer' => 'عميل جديد',

View File

@ -191,6 +191,14 @@ return [
],
'customer' => [
'compare' => [
'text' => 'Compare',
'compare_similar_items' => 'Compare Similar Items',
'added' => 'Item successfully added to compare list',
'already_added' => 'Item already added to compare list',
'removed' => 'Item successfully removed from compare list',
'empty-text' => "You don't have any items in your compare list",
],
'login-form' => [
'sign-up' => 'Sign up',
'new-customer' => 'New Customer',

View File

@ -8,6 +8,14 @@ return [
],
'customer' => [
'compare' => [
'text' => 'Comparar',
'compare_similar_items' => 'Comparar itens semelhantes',
'already_added' => 'Item já adicionado à lista de comparação',
'added' => 'Item adicionado com sucesso à lista de comparação',
'removed' => 'Item removido com sucesso da lista de comparação',
'empty-text' => "Você não possui nenhum item na sua lista de comparação",
],
'login-form' => [
'sign-up' => 'inscrever-se',
'new-customer' => 'Novo cliente',

View File

@ -1,32 +1,3 @@
<script type="text/x-template" id="star-ratings-template">
<div :class="`stars mr5 fs${size ? size : '16'} ${pushClass ? pushClass : ''}`">
<input
v-if="editable"
type="number"
:value="showFilled"
name="rating"
class="hidden" />
<i
:class="`material-icons ${editable ? 'cursor-pointer' : ''}`"
v-for="(rating, index) in parseInt(showFilled ? showFilled : 3)"
:key="`${index}${Math.random()}`"
@click="updateRating(index + 1)">
star
</i>
<template v-if="!hideBlank">
<i
:class="`material-icons ${editable ? 'cursor-pointer' : ''}`"
v-for="(blankStar, index) in (5 - (showFilled ? showFilled : 3))"
:key="`${index}${Math.random()}`"
@click="updateRating(showFilled + index + 1)">
star_border
</i>
</template>
</div>
</script>
<script type="text/x-template" id="cart-btn-template">
<button
type="button"
@ -147,6 +118,13 @@
{!! view_render_event('bagisto.shop.layout.header.cart-item.before') !!}
@include('shop::checkout.cart.mini-cart')
{!! view_render_event('bagisto.shop.layout.header.cart-item.after') !!}
{!! view_render_event('bagisto.shop.layout.header.compare.before') !!}
<a class="compare-btn unset" href="{{ route('velocity.product.compare') }}">
<i class="material-icons">compare_arrows</i>
<span>Compare</span>
</a>
{!! view_render_event('bagisto.shop.layout.header.compare.after') !!}
</div>
</div>
</script>
@ -211,7 +189,7 @@
</ul>
<ul type="none" class="category-wrapper">
<li v-for="(category, index) in JSON.parse(categories)">
<li v-for="(category, index) in JSON.parse(rootCategories)">
<a
class="unset"
:href="`${$root.baseUrl}/${category.slug}`">
@ -524,31 +502,6 @@
<script type="text/javascript">
(() => {
Vue.component('star-ratings', {
props: [
'ratings',
'size',
'hideBlank',
'pushClass',
'editable'
],
template: '#star-ratings-template',
data: function () {
return {
showFilled: this.ratings,
}
},
methods: {
updateRating: function (index) {
index = Math.abs(index);
this.editable ? this.showFilled = index : '';
}
},
})
Vue.component('cart-btn', {
template: '#cart-btn-template',

View File

@ -98,7 +98,6 @@
</div>
</div>
</div>
</div>
@else
<div class="dropdown disable-active">

View File

@ -0,0 +1,182 @@
@extends('shop::layouts.master')
@section('page_title')
{{ __('velocity::app.customer.compare.compare_similar_items') }}
@endsection
@section('content-wrapper')
@php
$attributeRepository = app('\Webkul\Attribute\Repositories\AttributeRepository');
$comparableAttributes = $attributeRepository->findByField('is_comparable', 1);
@endphp
<compare-product></compare-product>
@endsection
@push('scripts')
<script type="text/x-template" id="compare-product-template">
<section class="cart-details row no-margin col-12">
<h1 class="fw6 col-6">
{{ __('velocity::app.customer.compare.compare_similar_items') }}
</h1>
<div class="col-6" v-if="products.length > 0">
<button class="theme-btn light pull-right" @click="removeProductCompare('all')">Clear All</button>
</div>
{!! view_render_event('bagisto.shop.customers.account.compare.view.before') !!}
<div class="row compare-products col-12 ml0">
<template v-if="products.length > 0">
@php
$comparableAttributes = $comparableAttributes->toArray();
array_splice($comparableAttributes, 1, 0, [[
'code' => 'image',
'admin_name' => 'Product Image'
]]);
array_splice($comparableAttributes, 2, 0, [[
'code' => 'addToCartHtml',
'admin_name' => 'Actions'
]]);
@endphp
@foreach ($comparableAttributes as $attribute)
<div class="row col-12 pr-0 mt15">
<div class="col-2">
<span class="fs16">{{ $attribute['admin_name'] }}</span>
</div>
<div class="col" :key="`title-${index}`" v-for="(product, index) in products">
@if ($attribute['code'] == 'name')
<a :href="`${$root.baseUrl}/${isCustomer ? product.url_key : product.slug}`" class="unset">
<h1 class="fw6 fs18" v-text="product['{{ $attribute['code'] }}']"></h1>
</a>
@elseif ($attribute['code'] == 'image')
<a :href="`${$root.baseUrl}/${isCustomer ? product.url_key : product.slug}`" class="unset">
<img :src="product['{{ $attribute['code'] }}']" class="image-wrapper"></span>
</a>
@elseif ($attribute['code'] == 'price')
<span v-html="product['priceHTML']"></span>
@elseif ($attribute['code'] == 'addToCartHtml')
<div v-html="product['addToCartHtml']"></div>
<i class="material-icons cross fs16" @click="removeProductCompare(isCustomer ? product.id : product.slug)">close</i>
@else
<span v-html="product['{{ $attribute['code'] }}']"></span>
@endif
</div>
</div>
@endforeach
</template>
<span v-if="isProductListLoaded && products.length == 0">
@{{ __('customer.compare.empty-text') }}
</span>
</div>
{!! view_render_event('bagisto.shop.customers.account.compare.view.after') !!}
</section>
</script>
<script>
Vue.component('compare-product', {
template: '#compare-product-template',
data: function () {
return {
'products': [],
'isProductListLoaded': false,
'isCustomer': '{{ auth()->guard('customer')->user() ? "true" : "false" }}' == "true",
}
},
mounted: function () {
this.getComparedProducts();
},
methods: {
'getComparedProducts': function () {
if (this.isCustomer) {
var data = {
params: {
data: true,
}
};
} else {
let items = JSON.parse(window.localStorage.getItem('compared_product'));
items = items ? items.join('&') : '';
var data = {
params: {
items,
data: true,
}
};
}
this.$http.get(`${this.$root.baseUrl}/comparison`, data)
.then(response => {
this.isProductListLoaded = true;
this.products = response.data.products
})
.catch(error => {
console.log(this.__('error.something-went-wrong'));
});
},
'removeProductCompare': function (productId) {
if (this.isCustomer) {
this.$http.delete(`${this.$root.baseUrl}/comparison?productId=${productId}`)
.then(response => {
if (productId == 'all') {
this.$set(this, 'products', this.products.filter(product => false));
} else {
this.$set(this, 'products', this.products.filter(product => product.id != productId));
}
window.showAlert(`alert-${response.data.status}`, response.data.label, response.data.message);
})
.catch(error => {
console.log(this.__('error.something-went-wrong'));
});
} else {
let existingItems = window.localStorage.getItem('compared_product');
existingItems = JSON.parse(existingItems);
if (productId == "all") {
updatedItems = [];
this.$set(this, 'products', []);
} else {
updatedItems = existingItems.filter(item => item != productId);
this.$set(this, 'products', this.products.filter(product => product.slug != productId));
}
window.localStorage.setItem('compared_product', JSON.stringify(updatedItems));
window.showAlert(
`alert-success`,
this.__('shop.general.alert.success'),
`${this.__('customer.compare.removed')}`
);
}
},
'getAddToCartHtml': function (input) {
const { render, staticRenderFns } = Vue.compile(input);
const _staticRenderFns = this.$options.staticRenderFns = staticRenderFns;
try {
var output = render.call(this, this.$createElement)
} catch (exception) {
console.log(this.__('error.something-went-wrong'));
}
this.$options.staticRenderFns = _staticRenderFns
return output;
}
}
});
</script>
@endpush

View File

@ -18,6 +18,11 @@
$subMenuCollection['orders'] = $menuItem['children']['orders'];
$subMenuCollection['downloadables'] = $menuItem['children']['downloadables'];
$subMenuCollection['wishlist'] = $menuItem['children']['wishlist'];
$subMenuCollection['compare'] = [
'key' => 'account.compare',
'url' => route('velocity.product.compare'),
'name' => 'velocity::app.customer.compare.text',
];
$subMenuCollection['reviews'] = $menuItem['children']['reviews'];
$subMenuCollection['address'] = $menuItem['children']['address'];
} catch (\Exception $exception) {
@ -26,7 +31,7 @@
@endphp
@foreach ($subMenuCollection as $index => $subMenuItem)
<li class="{{ $menu->getActive($subMenuItem) }}">
<li class="{{ $menu->getActive($subMenuItem) }}" title="{{ trans($subMenuItem['name']) }}">
<a class="unset fw6 full-width" href="{{ $subMenuItem['url'] }}">
<i class="icon {{ $index }} text-down-3"></i>
<span>{{ trans($subMenuItem['name']) }}<span>

View File

@ -44,8 +44,6 @@
{{ __('shop::app.customer.account.profile.index.edit') }}
</a>
</span>
<div class="horizontal-rule"></div>
</div>
{!! view_render_event('bagisto.shop.customers.account.profile.view.before', ['customer' => $customer]) !!}

View File

@ -132,25 +132,23 @@
<script type="text/javascript">
(() => {
var showAlert = (messageType, messageLabel, message) => {
window.showAlert = (messageType, messageLabel, message) => {
if (messageType && message !== '') {
let html = `<div class="alert ${messageType} alert-dismissible" id="alert">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<strong>${messageLabel} !</strong> ${message}.
</div>`;
document.body.innerHTML += html;
$('body').append(html);
window.setTimeout(() => {
$(".alert").fadeTo(500, 0).slideUp(500, () => {
$(this).remove();
});
$(".alert").remove();
}, 5000);
}
}
let messageType = 'alert-success';
let messageLabel = 'dsfghjkl';
let messageType = '';
let messageLabel = '';
@if ($message = session('success'))
messageType = 'alert-success';
@ -167,7 +165,7 @@
@endif
if (messageType && '{{ $message }}' !== '') {
showAlert(messageType, messageLabel, '{{ $message }}');
window.showAlert(messageType, messageLabel, '{{ $message }}');
}
window.serverErrors = [];

View File

@ -86,6 +86,10 @@
<a href="{{ route('customer.wishlist.index') }}" class="unset">{{ __('shop::app.header.wishlist') }}</a>
</li>
<li>
<a href="{{ route('velocity.product.compare') }}" class="unset">{{ __('velocity::app.customer.compare.text') }}</a>
</li>
<li>
<a href="{{ route('customer.session.destroy') }}" class="unset">{{ __('shop::app.header.logout') }}</a>
</li>

View File

@ -1,30 +1,8 @@
{!! view_render_event('bagisto.shop.products.add_to_cart.before', ['product' => $product]) !!}
<div class="row mx-0 col-12 no-padding">
<div class="add-to-cart-btn pl0">
@if (isset($form) && !$form)
<button
type="submit"
{{ ! $product->isSaleable() ? 'disabled' : '' }}
class="btn btn-add-to-cart {{ $addToCartBtnClass ?? '' }}">
@if (! (isset($showCartIcon) && !$showCartIcon))
<i class="material-icons text-down-3">shopping_cart</i>
@endif
<span class="fs14 fw6 text-uppercase text-up-4">
{{ __('shop::app.products.add-to-cart') }}
</span>
</button>
@else
<form
method="POST"
action="{{ route('cart.add', $product->product_id) }}">
@csrf
<input type="hidden" name="product_id" value="{{ $product->product_id }}">
<input type="hidden" name="quantity" value="1">
<div class="row mx-0 col-12 no-padding">
<div class="add-to-cart-btn pl0">
@if (isset($form) && !$form)
<button
type="submit"
{{ ! $product->isSaleable() ? 'disabled' : '' }}
@ -35,28 +13,66 @@
@endif
<span class="fs14 fw6 text-uppercase text-up-4">
{{ $btnText ?? __('shop::app.products.add-to-cart') }}
{{ __('shop::app.products.add-to-cart') }}
</span>
</button>
</form>
@else
<form method="POST" action="{{ route('cart.add', $product->product_id) }}">
@csrf
{{-- <add-to-cart
form="true"
csrf-token='{{ csrf_token() }}'
product-id="{{ $product->product_id }}"
add-class-to-btn="{{ $addToCartBtnClass ?? '' }}"
is-enable={{ ! $product->isSaleable() ? 'false' : 'true' }}
show-cart-icon={{ !(isset($showCartIcon) && !$showCartIcon) }}
btn-text="{{ $btnText ?? __('shop::app.products.add-to-cart') }}">
</add-to-cart> --}}
<input type="hidden" name="quantity" value="1" />
<input type="hidden" name="product_id" value="{{ $product->product_id }}" />
<button
type="submit"
{{ ! $product->isSaleable() ? 'disabled' : '' }}
class="btn btn-add-to-cart {{ $addToCartBtnClass ?? '' }}">
@if (! (isset($showCartIcon) && !$showCartIcon))
<i class="material-icons text-down-3">shopping_cart</i>
@endif
<span class="fs14 fw6 text-uppercase text-up-4">
{{ $btnText ?? __('shop::app.products.add-to-cart') }}
</span>
</button>
</form>
{{-- <add-to-cart
form="true"
csrf-token='{{ csrf_token() }}'
product-id="{{ $product->product_id }}"
add-class-to-btn="{{ $addToCartBtnClass ?? '' }}"
is-enable={{ ! $product->isSaleable() ? 'false' : 'true' }}
show-cart-icon={{ !(isset($showCartIcon) && !$showCartIcon) }}
btn-text="{{ $btnText ?? __('shop::app.products.add-to-cart') }}">
</add-to-cart> --}}
@endif
</div>
@if (isset($showCompare) && $showCompare)
@auth('customer')
<compare-component
customer="true"
productId="{{ $product->id }}"
slug="{{ $product->url_key }}"
></compare-component>
@endif
@guest('customer')
<compare-component
customer="false"
productId="{{ $product->id }}"
slug="{{ $product->url_key }}"
></compare-component>
@endif
@endif
@if (! (isset($showWishlist) && !$showWishlist))
@include('shop::products.wishlist', [
'addClass' => $addWishlistClass ?? ''
])
@endif
</div>
@if (! (isset($showWishlist) && !$showWishlist))
@include('shop::products.wishlist', [
'addClass' => $addWishlistClass ?? ''
])
@endif
</div>
{!! view_render_event('bagisto.shop.products.add_to_cart.after', ['product' => $product]) !!}

View File

@ -18,7 +18,7 @@
font-size: 18px;
font-weight: 600;
}
@media only screen and (max-width: 992px) {
.main-content-wrapper .vc-header {
box-shadow: unset;
@ -61,7 +61,7 @@
@endif
</div>
<div class="col-12">
<div class="col-12 no-padding">
<div class="hero-image">
@if (!is_null($category->image))
<img class="logo" src="{{ $category->image_url }}" />

View File

@ -24,7 +24,7 @@
.related-products {
width: 100%;
}
.recently-viewed {
margin-top: 20px;
}
@ -88,6 +88,7 @@
@include ('shop::products.add-to-cart', [
'form' => false,
'product' => $product,
'showCompare' => true,
'showCartIcon' => false,
])
</div>