commit
41ba95c6cc
|
|
@ -6,6 +6,7 @@ end_of_line = lf
|
|||
insert_final_newline = false
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
quote_type = single
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ about: 'Report a general issue.'
|
|||
<!--- Please select the version of bagisto that you are using. -->
|
||||
#### Bagisto version
|
||||
- [ ] master branch
|
||||
- [ ] 1.3.2
|
||||
- [ ] 1.3.1
|
||||
- [ ] 1.3.0
|
||||
- [ ] 1.2.0
|
||||
|
||||
### Steps to reproduce
|
||||
<!--- It is important to provide a set of clear steps to reproduce this bug.If relevant please include code samples. -->
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
## Description
|
||||
<!--- Please mention issue #id and use comma if your PR solves multiple issues -->
|
||||
<!--- Please describe your changes in detail -->
|
||||
## Issue Reference
|
||||
<!--- Please mention issue #id or use a comma if your pull request solves multiple issues. -->
|
||||
|
||||
## How to test this
|
||||
<!--- Please describe in detail how to test the changes made in this PR -->
|
||||
## Description
|
||||
<!--- Please describe your changes in detail. -->
|
||||
|
||||
## How To Test This?
|
||||
<!--- Please describe in detail how to test the changes made in this pull request. -->
|
||||
|
||||
## Documentation
|
||||
- [ ] My pull request requires a update on the documentation repository.
|
||||
<!--- Please describe in detail what needs to be changed --->
|
||||
- [ ] My pull request requires an update on the documentation repository.
|
||||
<!--- Please describe in detail what needs to be changed. --->
|
||||
|
|
|
|||
|
|
@ -2,6 +2,200 @@
|
|||
|
||||
This changelog consists of the bug & security fixes and new features being included in the releases listed below.
|
||||
|
||||
## **v1.3.2 (7th of August 2021)** - *Release*
|
||||
|
||||
* #5020 [feature] - Webvital score improvement.
|
||||
|
||||
* #4855 [feature] - Autofilling of quantity.
|
||||
|
||||
* #4632 [feature] - Gooogle captcha integration.
|
||||
|
||||
* #4557 [feature] - Feature for sorting product review at customer's end.
|
||||
|
||||
* #4463 [feature] - Show prices with or without taxes.
|
||||
|
||||
* #4257 [feature] - Multi-lang support in admin.
|
||||
|
||||
* #4102 [feature] - Payment history for orders.
|
||||
|
||||
* #3477 [feature] - Image column in configurable products for variants.
|
||||
|
||||
* #3453 [feature] - Automatic invoice generation.
|
||||
|
||||
* #4927 [enhancement] - Allow the admin to set a payment term for invoices.
|
||||
|
||||
* #4926 [enhancement] - Allow admin to set an invoice prefix and the first invoice number.
|
||||
|
||||
* #4911 [enhancement] - Default variant selection for configurable product.
|
||||
|
||||
* #4901 [enhancement] - Configurable product addition issue.
|
||||
|
||||
* #4767 [enhancement] - PHP 8 Support.
|
||||
|
||||
* #4449 [enhancement] - Laravel 8 Support.
|
||||
|
||||
* #3834 [enhancement] - Ability to use multiple datagrids on single page.
|
||||
|
||||
* #3251 [enhancement] - Add orders list to the customers details view.
|
||||
|
||||
* #5053 [fixed] - showing validation on input fields while loading velocity
|
||||
|
||||
* #5046 [fixed] - Add to cart button is not working in compare page for default theme.
|
||||
|
||||
* #5045 [fixed] - Not getting product images where cache is exist.
|
||||
|
||||
* #5042 [fixed] - Update the alert message when edit and save customer address.
|
||||
|
||||
* #5033 [fixed] - Order status options after invoice generation on payment methods.
|
||||
|
||||
* #5029 [fixed] - Header menu content list layout need to fix.
|
||||
|
||||
* #5027 [fixed] - Fix customer account menu visibility in safari browser.
|
||||
|
||||
* #5018 [fixed] - Invoice ID is not recognized in transactions when invoice id contains custom prefix/suffix.
|
||||
|
||||
* #5013 [fixed] - No warning visible when user password doesn't match on the reset password page.
|
||||
|
||||
* #5011 [fixed] - Admin filter options are not working in Safari.
|
||||
|
||||
* #4992 [fixed] - Products image are getting stretch on search page.
|
||||
|
||||
* #4989 [fixed] - In sales, the module that creates refund subtotal is showing different.
|
||||
|
||||
* #4977 [fixed] - Configurable products are not visible on the category page if allow out of stock is disabled.
|
||||
.
|
||||
* #4969 [fixed] - Muliselect attribute options ID should not visible in compare product.
|
||||
|
||||
* #4965 [fixed] - Filter labels in datagrids are not translated.
|
||||
|
||||
* #4964 [fixed] - Search icon is missing in velocity theme Datagrid.
|
||||
|
||||
* #4963 [fixed] - French locale translations are missing.
|
||||
|
||||
* #4962 [fixed] - Able to access downloadable products even I have not purchased.
|
||||
|
||||
* #4960 [fixed] - The invoice date is missing on invoices.
|
||||
|
||||
* #4959 [fixed] - Getting exception when merging guest cart with customer cart with the configurable item.
|
||||
|
||||
* #4951 [fixed] - Real-time compare number is not decreased when deleting a product from compare page.
|
||||
|
||||
* #4948 [fixed] - Translation issue for the minimum order at cart checkout.
|
||||
|
||||
* #4947 [fixed] - Getting all invoices (that are not linked to customer or customer's order) in the customer section in the admin panel.
|
||||
|
||||
* #4941 [fixed] - The locale option should be visible with fields that are locale-based.
|
||||
|
||||
* #4935 [fixed] - Slider is not removed from the store if slider date gets expired.
|
||||
|
||||
* #4931 [fixed] - Root category name is missing when admin locale is not en.
|
||||
|
||||
* #4924 [fixed] - The coupon code button should not disable if one coupon code is already applied.
|
||||
|
||||
* #4921 [fixed] - Flag icons are missing when the locale is not en.
|
||||
|
||||
* #4903 [fixed] - Contribution guide is missing.
|
||||
|
||||
* #4896 [fixed] - Group product sort order functionality is not working.
|
||||
|
||||
* #4886 [fixed] - Make Sample optional for downloadable products.
|
||||
|
||||
* #4885 [fixed] - Hide shipping for virtual products
|
||||
|
||||
* #4854 [fixed] - Filtering customer address page is always redirect to the customer profile tab.
|
||||
|
||||
* #4848 [fixed] - Fix selected filter options alignment at customer panel.
|
||||
|
||||
* #4847 [fixed] - Add ACL for customer order list.
|
||||
|
||||
* #4840 [fixed] - Pagination alignment issue on customer end.
|
||||
|
||||
* #4827 [fixed] - Shop by category disappears on hover.
|
||||
|
||||
* #4823 [fixed] - UI bug at customer Invoice page if multiple invoices exist for same order id.
|
||||
|
||||
* #4818 [fixed] - Getting qty error when move item to cart from the wishlist.
|
||||
|
||||
* #4813 [fixed] - Compare product in velocity theme showing duplicated attribute after adding a new attribute family.
|
||||
|
||||
* #4811 [fixed] - Getting error when redirect on review page.
|
||||
|
||||
* #4807 [fixed] - Category logo icon is missing in API.
|
||||
|
||||
* #4806 [fixed] - Not able to see the configurable products in the API.
|
||||
|
||||
* #4804 [fixed] - The city field is missing in order confirmation emails.
|
||||
|
||||
* #4800 [fixed] - Filter is not working in customer grid.
|
||||
|
||||
* #4799 [fixed] - Product image resizing.
|
||||
|
||||
* #4794 [fixed] - Admin logo is getting hidden when scrolling down the menu bar.
|
||||
|
||||
* #4779 [fixed] - Image search is not working when out of stock is disabled.
|
||||
|
||||
* #4773 [fixed] - Category condition is not getting set in catalog rule.
|
||||
|
||||
* #4771 [fixed] - Datetime component should be enhanced as date component in UI package.
|
||||
|
||||
* #4758 [fixed] - Bug when adding an item twice in the cart from the API.
|
||||
|
||||
* #4752 [fixed] - Add endpoints for transactions API Done Enhancement.
|
||||
|
||||
* #4751 [fixed] - The sidebar menu icon should be removed from admin.
|
||||
|
||||
* #4748 [fixed] - Address is not saved on checkout.
|
||||
|
||||
* #4735 [fixed] - Price filter issue.
|
||||
|
||||
* #4730 [fixed] - All products are getting deleted when the associated category is deleted.
|
||||
|
||||
* #4729 [fixed] - Products do not exist inside a category, still they are visible on the category page.
|
||||
|
||||
* #4727 [fixed] - Error `addToCartHtml` is not defined on the compare page.
|
||||
|
||||
* #4722 [fixed] - Getting exception on wishlist when adding a configurable item on wishlist.
|
||||
|
||||
* #4715 [fixed] - Product name is breaking in invoice PDF.
|
||||
|
||||
* #4713 [fixed] - Paypal IPN Issue Fixed - SA6.
|
||||
|
||||
* #4710 [fixed] - Fixed currencies "value"s and "phone" fields formated for API.
|
||||
|
||||
* #4709 [fixed] - Getting exception when update inactive item on cart.
|
||||
|
||||
* #4708 [fixed] - Getting issue while selecting variant with no image.
|
||||
|
||||
* #4707 [fixed] - Fixed admin theme not loading with custom admin URL.
|
||||
|
||||
* #4702 [fixed] - Issue during exporting customers data.
|
||||
|
||||
* #4698 [fixed] - Category slug should not translation based.
|
||||
|
||||
* #4691 [fixed] - Distorted image issue.
|
||||
|
||||
* #4690 [fixed] - Variant images are not visible in a sorted manner as uploaded in the backend.
|
||||
|
||||
* #4686 [fixed] - Configurable item is still visible on the search page when out of stock is disabled.
|
||||
|
||||
* #4685 [fixed] - Blank space remains on the homepage when disabling out-of-stock items from the backend.
|
||||
|
||||
* #4682 [fixed] - Catalog rules and product price filter.
|
||||
|
||||
* #4680 [fixed] - Check out page extremely slow.
|
||||
|
||||
* #4677 [fixed] - API addresses, returns an error on create + not all fields are manipulated API.
|
||||
|
||||
* #4668 [fixed] - Customer profile header is missing in responsive view.
|
||||
|
||||
* #4564 [fixed] - Getting exception on admin interface when setup using webinstaller.
|
||||
|
||||
* #4519 [fixed] - Tax should not be state or Pincode-dependent. It should be product category-dependent.
|
||||
|
||||
* #3902 [fixed] - Duplicate order number getting generated when placed order simultaneously.
|
||||
|
||||
* #3196 [fixed] - L x W x H/D on product description.
|
||||
|
||||
## **v1.3.1 (22nd of February 2021)** - *Release*
|
||||
|
||||
* #4659 [fixed] - Only show defaults option in Shipping.
|
||||
|
|
@ -516,8 +710,6 @@ This changelog consists of the bug & security fixes and new features being inclu
|
|||
|
||||
* #3457 [fixed] - number indicator are hidden on wishlist or compare icon RTL format
|
||||
|
||||
* #3453 [fixed] - Invoice state is always set to paid
|
||||
|
||||
* #3451 [fixed] - Change request regarding shipments
|
||||
|
||||
* #3447 [fixed] - By default social login should be enabled
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
4. [Installation & Configuration](#installation-and-configuration)
|
||||
5. [License](#license)
|
||||
6. [Security Vulnerabilities](#security-vulnerabilities)
|
||||
7. [Miscellaneous](#miscellaneous)
|
||||
7. [Modules](#modules)
|
||||
8. [Miscellaneous](#miscellaneous)
|
||||
|
||||
### Introduction
|
||||
|
||||
|
|
@ -139,6 +140,11 @@ Bagisto is a truly opensource E-Commerce framework which will always be free und
|
|||
### Security Vulnerabilities
|
||||
Please don't disclose security vulnerabilities publicly. If you find any security vulnerability in Bagisto then please email us: mailto:support@bagisto.com.
|
||||
|
||||
### Modules
|
||||
[Available Modules](https://bagisto.com/en/extensions)
|
||||
|
||||
Need something else? Email us at support@bagisto.com.
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
#### Contribute
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@ class Kernel extends HttpKernel
|
|||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
\Webkul\Core\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Webkul\Core\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Webkul\Core\Http\Middleware\SecureHeaders::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
"watch-poll": "npm run watch -- --watch-poll",
|
||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"prod": "npm run production",
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"postinstall": "opencollective-postinstall"
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.21.0",
|
||||
|
|
@ -25,12 +24,6 @@
|
|||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"opencollective": "^1.0.3",
|
||||
"opencollective-postinstall": "^2.0.1",
|
||||
"vee-validate": "^3.3.0"
|
||||
},
|
||||
"collective": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bagisto"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"/js/admin.js": "/js/admin.js?id=daa03d172fe04288dd85",
|
||||
"/js/admin.js": "/js/admin.js?id=8bcdcf3b86191d1739a5",
|
||||
"/css/admin.css": "/css/admin.css?id=b24aa6544b82f674840f"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Core\Models\Locale;
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
|
||||
class CategoryDataGrid extends DataGrid
|
||||
|
|
@ -11,17 +12,32 @@ class CategoryDataGrid extends DataGrid
|
|||
|
||||
protected $sortOrder = 'desc';
|
||||
|
||||
protected $locale = 'all';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->locale = core()->getRequestedLocaleCode();
|
||||
}
|
||||
|
||||
public function prepareQueryBuilder()
|
||||
{
|
||||
if ($this->locale === 'all') {
|
||||
$whereInLocales = Locale::query()->pluck('code')->toArray();
|
||||
} else {
|
||||
$whereInLocales = [$this->locale];
|
||||
}
|
||||
|
||||
$queryBuilder = DB::table('categories as cat')
|
||||
->select('cat.id as category_id', 'ct.name', 'cat.position', 'cat.status', 'ct.locale',
|
||||
DB::raw('COUNT(DISTINCT ' . DB::getTablePrefix() . 'pc.product_id) as count'))
|
||||
->leftJoin('category_translations as ct', function($leftJoin) {
|
||||
->leftJoin('category_translations as ct', function($leftJoin) use($whereInLocales) {
|
||||
$leftJoin->on('cat.id', '=', 'ct.category_id')
|
||||
->where('ct.locale', app()->getLocale());
|
||||
->whereIn('ct.locale', $whereInLocales);
|
||||
})
|
||||
->leftJoin('product_categories as pc', 'cat.id', '=', 'pc.category_id')
|
||||
->groupBy('cat.id');
|
||||
->groupBy('cat.id', 'ct.locale',);
|
||||
|
||||
|
||||
$this->addFilter('status', 'cat.status');
|
||||
|
|
|
|||
|
|
@ -2,30 +2,55 @@
|
|||
|
||||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Core\Models\Channel;
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class SliderDataGrid extends DataGrid
|
||||
{
|
||||
/**
|
||||
* Set index columns, ex: id.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $index = 'id';
|
||||
|
||||
/**
|
||||
* Default sort order of datagrid.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sortOrder = 'desc';
|
||||
|
||||
/**
|
||||
* Locale.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $locale = 'all';
|
||||
|
||||
/**
|
||||
* Channel.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $channel = 'all';
|
||||
|
||||
/**
|
||||
* Contains the keys for which extra filters to render.
|
||||
*
|
||||
* @var string[]
|
||||
**/
|
||||
*/
|
||||
protected $extraFilters = [
|
||||
'channels',
|
||||
'locales',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create datagrid instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
|
@ -43,16 +68,23 @@ class SliderDataGrid extends DataGrid
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare query builder.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepareQueryBuilder()
|
||||
{
|
||||
$dbPrefix = DB::getTablePrefix();
|
||||
|
||||
$queryBuilder = DB::table('sliders as sl')
|
||||
->select('sl.id', 'sl.title', 'sl.locale', 'ct.channel_id', 'ct.name', 'ch.code')
|
||||
->leftJoin('channels as ch', 'sl.channel_id', '=', 'ch.id')
|
||||
->leftJoin('channel_translations as ct', 'ch.id', '=', 'ct.channel_id')
|
||||
->where('ct.locale', app()->getLocale());
|
||||
->select('sl.id', 'sl.title', 'sl.locale', 'ct.channel_id', 'ct.name', 'ch.code')
|
||||
->leftJoin('channels as ch', 'sl.channel_id', '=', 'ch.id')
|
||||
->leftJoin('channel_translations as ct', 'ch.id', '=', 'ct.channel_id')
|
||||
->where('ct.locale', app()->getLocale());
|
||||
|
||||
if ($this->locale !== 'all') {
|
||||
$queryBuilder->whereRaw("find_in_set(?, sl.locale)", [$this->locale]);
|
||||
$queryBuilder->whereRaw("find_in_set(?, {$dbPrefix}sl.locale)", [$this->locale]);
|
||||
}
|
||||
|
||||
if ($this->channel !== 'all') {
|
||||
|
|
@ -68,6 +100,11 @@ class SliderDataGrid extends DataGrid
|
|||
$this->setQueryBuilder($queryBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addColumns()
|
||||
{
|
||||
$this->addColumn([
|
||||
|
|
@ -107,6 +144,11 @@ class SliderDataGrid extends DataGrid
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare actions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepareActions()
|
||||
{
|
||||
$this->addAction([
|
||||
|
|
@ -123,4 +165,4 @@ class SliderDataGrid extends DataGrid
|
|||
'icon' => 'icon trash-icon',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
namespace Webkul\Admin\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
use Webkul\Sales\Repositories\OrderRepository;
|
||||
use Webkul\Sales\Repositories\OrderItemRepository;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Customer\Repositories\CustomerRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Sales\Repositories\InvoiceRepository;
|
||||
use Webkul\Sales\Repositories\OrderItemRepository;
|
||||
use Webkul\Sales\Repositories\OrderRepository;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
|
|
@ -19,56 +20,63 @@ class DashboardController extends Controller
|
|||
protected $_config;
|
||||
|
||||
/**
|
||||
* OrderRepository object
|
||||
* Order repository instance.
|
||||
*
|
||||
* @var \Webkul\Sales\Repositories\OrderRepository
|
||||
*/
|
||||
protected $orderRepository;
|
||||
|
||||
/**
|
||||
* OrderItemRepository object
|
||||
* Order item repository instance.
|
||||
*
|
||||
* @var \Webkul\Sales\Repositories\OrderItemRepository
|
||||
*/
|
||||
protected $orderItemRepository;
|
||||
|
||||
/**
|
||||
* CustomerRepository object
|
||||
* Invoice repository instance.
|
||||
*
|
||||
* @var \Webkul\Sales\Repositories\InvoiceRepository
|
||||
*/
|
||||
protected $invoiceRepository;
|
||||
|
||||
/**
|
||||
* Customer repository instance.
|
||||
*
|
||||
* @var \Webkul\Customer\Repositories\CustomerRepository
|
||||
*/
|
||||
protected $customerRepository;
|
||||
|
||||
/**
|
||||
* ProductInventoryRepository object
|
||||
* Product inventory repository instance.
|
||||
*
|
||||
* @var \Webkul\Product\Repositories\ProductInventoryRepository
|
||||
*/
|
||||
protected $productInventoryRepository;
|
||||
|
||||
/**
|
||||
* string object
|
||||
* Start date.
|
||||
*
|
||||
* @var \Illuminate\Support\Carbon
|
||||
*/
|
||||
protected $startDate;
|
||||
|
||||
/**
|
||||
* string object
|
||||
* Last start date.
|
||||
*
|
||||
* @var \Illuminate\Support\Carbon
|
||||
*/
|
||||
protected $lastStartDate;
|
||||
|
||||
/**
|
||||
* string object
|
||||
* End date.
|
||||
*
|
||||
* @var \Illuminate\Support\Carbon
|
||||
*/
|
||||
protected $endDate;
|
||||
|
||||
/**
|
||||
* string object
|
||||
* Last end date.
|
||||
*
|
||||
* @var \Illuminate\Support\Carbon
|
||||
*/
|
||||
|
|
@ -86,10 +94,10 @@ class DashboardController extends Controller
|
|||
public function __construct(
|
||||
OrderRepository $orderRepository,
|
||||
OrderItemRepository $orderItemRepository,
|
||||
InvoiceRepository $invoiceRepository,
|
||||
CustomerRepository $customerRepository,
|
||||
ProductInventoryRepository $productInventoryRepository
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->_config = request('_config');
|
||||
|
||||
$this->middleware('admin');
|
||||
|
|
@ -98,27 +106,13 @@ class DashboardController extends Controller
|
|||
|
||||
$this->orderItemRepository = $orderItemRepository;
|
||||
|
||||
$this->invoiceRepository = $invoiceRepository;
|
||||
|
||||
$this->customerRepository = $customerRepository;
|
||||
|
||||
$this->productInventoryRepository = $productInventoryRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns percentage difference
|
||||
*
|
||||
* @param int $previous
|
||||
* @param int $current
|
||||
* @return int
|
||||
*/
|
||||
public function getPercentageChange($previous, $current)
|
||||
{
|
||||
if (! $previous) {
|
||||
return $current ? 100 : 0;
|
||||
}
|
||||
|
||||
return ($current - $previous) / $previous * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
|
|
@ -129,9 +123,12 @@ class DashboardController extends Controller
|
|||
$this->setStartEndDate();
|
||||
|
||||
$statistics = [
|
||||
/**
|
||||
* These are the stats with percentage change.
|
||||
*/
|
||||
'total_customers' => [
|
||||
'previous' => $previous = $this->getCustomersBetweenDates($this->lastStartDate, $this->lastEndDate)->count(),
|
||||
'current' => $current = $this->getCustomersBetweenDates($this->startDate, $this->endDate)->count(),
|
||||
'previous' => $previous = $this->getCustomersBetweenDates($this->lastStartDate, $this->lastEndDate),
|
||||
'current' => $current = $this->getCustomersBetweenDates($this->startDate, $this->endDate),
|
||||
'progress' => $this->getPercentageChange($previous, $current),
|
||||
],
|
||||
'total_orders' => [
|
||||
|
|
@ -149,6 +146,11 @@ class DashboardController extends Controller
|
|||
'current' => $current = $this->currentOrders()->avg('base_grand_total_invoiced') - $this->currentOrders()->avg('base_grand_total_refunded'),
|
||||
'progress' => $this->getPercentageChange($previous, $current),
|
||||
],
|
||||
|
||||
/**
|
||||
* These are the normal stats.
|
||||
*/
|
||||
'total_unpaid_invoices' => $this->getTotalPendingInvoices(),
|
||||
'top_selling_categories' => $this->getTopSellingCategories(),
|
||||
'top_selling_products' => $this->getTopSellingProducts(),
|
||||
'customer_with_most_sales' => $this->getCustomerWithMostSales(),
|
||||
|
|
@ -168,28 +170,69 @@ class DashboardController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the list of top selling categories
|
||||
* Sets start and end date.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setStartEndDate()
|
||||
{
|
||||
$this->startDate = request()->get('start')
|
||||
? Carbon::createFromTimeString(request()->get('start') . " 00:00:01")
|
||||
: Carbon::createFromTimeString(Carbon::now()->subDays(30)->format('Y-m-d') . " 00:00:01");
|
||||
|
||||
$this->endDate = request()->get('end')
|
||||
? Carbon::createFromTimeString(request()->get('end') . " 23:59:59")
|
||||
: Carbon::now();
|
||||
|
||||
if ($this->endDate > Carbon::now()) {
|
||||
$this->endDate = Carbon::now();
|
||||
}
|
||||
|
||||
$this->lastStartDate = clone $this->startDate;
|
||||
$this->lastEndDate = clone $this->startDate;
|
||||
|
||||
$this->lastStartDate->subDays($this->startDate->diffInDays($this->endDate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns percentage difference
|
||||
*
|
||||
* @param int $previous
|
||||
* @param int $current
|
||||
* @return int
|
||||
*/
|
||||
public function getPercentageChange($previous, $current)
|
||||
{
|
||||
if (! $previous) {
|
||||
return $current ? 100 : 0;
|
||||
}
|
||||
|
||||
return ($current - $previous) / $previous * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of top selling categories.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getTopSellingCategories()
|
||||
{
|
||||
return $this->orderItemRepository->getModel()
|
||||
->leftJoin('products', 'order_items.product_id', 'products.id')
|
||||
->leftJoin('product_categories', 'products.id', 'product_categories.product_id')
|
||||
->leftJoin('categories', 'product_categories.category_id', 'categories.id')
|
||||
->leftJoin('category_translations', 'categories.id', 'category_translations.category_id')
|
||||
->where('category_translations.locale', app()->getLocale())
|
||||
->where('order_items.created_at', '>=', $this->startDate)
|
||||
->where('order_items.created_at', '<=', $this->endDate)
|
||||
->addSelect(DB::raw('SUM(qty_invoiced - qty_refunded) as total_qty_invoiced'))
|
||||
->addSelect(DB::raw('COUNT(' . DB::getTablePrefix() . 'products.id) as total_products'))
|
||||
->addSelect('order_items.id', 'categories.id as category_id', 'category_translations.name')
|
||||
->groupBy('categories.id')
|
||||
->havingRaw('SUM(qty_invoiced - qty_refunded) > 0')
|
||||
->orderBy('total_qty_invoiced', 'DESC')
|
||||
->limit(5)
|
||||
->get();
|
||||
->leftJoin('products', 'order_items.product_id', 'products.id')
|
||||
->leftJoin('product_categories', 'products.id', 'product_categories.product_id')
|
||||
->leftJoin('categories', 'product_categories.category_id', 'categories.id')
|
||||
->leftJoin('category_translations', 'categories.id', 'category_translations.category_id')
|
||||
->where('category_translations.locale', app()->getLocale())
|
||||
->where('order_items.created_at', '>=', $this->startDate)
|
||||
->where('order_items.created_at', '<=', $this->endDate)
|
||||
->addSelect(DB::raw('SUM(qty_invoiced - qty_refunded) as total_qty_invoiced'))
|
||||
->addSelect(DB::raw('COUNT(' . DB::getTablePrefix() . 'products.id) as total_products'))
|
||||
->addSelect('order_items.id', 'categories.id as category_id', 'category_translations.name')
|
||||
->groupBy('categories.id')
|
||||
->havingRaw('SUM(qty_invoiced - qty_refunded) > 0')
|
||||
->orderBy('total_qty_invoiced', 'DESC')
|
||||
->limit(5)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -200,36 +243,36 @@ class DashboardController extends Controller
|
|||
public function getStockThreshold()
|
||||
{
|
||||
return $this->productInventoryRepository->getModel()
|
||||
->leftJoin('products', 'product_inventories.product_id', 'products.id')
|
||||
->select(DB::raw('SUM(qty) as total_qty'))
|
||||
->addSelect('product_inventories.product_id')
|
||||
->groupBy('product_id')
|
||||
->orderBy('total_qty', 'ASC')
|
||||
->limit(5)
|
||||
->get();
|
||||
->leftJoin('products', 'product_inventories.product_id', 'products.id')
|
||||
->select(DB::raw('SUM(qty) as total_qty'))
|
||||
->addSelect('product_inventories.product_id')
|
||||
->groupBy('product_id')
|
||||
->orderBy('total_qty', 'ASC')
|
||||
->limit(5)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns top selling products
|
||||
* Returns top selling products.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getTopSellingProducts()
|
||||
{
|
||||
return $this->orderItemRepository->getModel()
|
||||
->select(DB::raw('SUM(qty_ordered) as total_qty_ordered'))
|
||||
->addSelect('id', 'product_id', 'product_type', 'name')
|
||||
->where('order_items.created_at', '>=', $this->startDate)
|
||||
->where('order_items.created_at', '<=', $this->endDate)
|
||||
->whereNull('parent_id')
|
||||
->groupBy('product_id')
|
||||
->orderBy('total_qty_ordered', 'DESC')
|
||||
->limit(5)
|
||||
->get();
|
||||
->select(DB::raw('SUM(qty_ordered) as total_qty_ordered'))
|
||||
->addSelect('id', 'product_id', 'product_type', 'name')
|
||||
->where('order_items.created_at', '>=', $this->startDate)
|
||||
->where('order_items.created_at', '<=', $this->endDate)
|
||||
->whereNull('parent_id')
|
||||
->groupBy('product_id')
|
||||
->orderBy('total_qty_ordered', 'DESC')
|
||||
->limit(5)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns top selling products
|
||||
* Returns cutomer with most sales.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
|
|
@ -238,48 +281,22 @@ class DashboardController extends Controller
|
|||
$dbPrefix = DB::getTablePrefix();
|
||||
|
||||
return $this->orderRepository->getModel()
|
||||
->leftJoin('refunds', 'orders.id', 'refunds.order_id')
|
||||
->select(DB::raw("(SUM({$dbPrefix}orders.base_grand_total) - SUM(IFNULL({$dbPrefix}refunds.base_grand_total, 0))) as total_base_grand_total"))
|
||||
->addSelect(DB::raw("COUNT({$dbPrefix}orders.id) as total_orders"))
|
||||
->addSelect('orders.id', 'customer_id', 'customer_email', 'customer_first_name', 'customer_last_name')
|
||||
->where('orders.created_at', '>=', $this->startDate)
|
||||
->where('orders.created_at', '<=', $this->endDate)
|
||||
->where('orders.status', '<>', 'closed')
|
||||
->where('orders.status', '<>', 'canceled')
|
||||
->groupBy('customer_email')
|
||||
->orderBy('total_base_grand_total', 'DESC')
|
||||
->limit(5)
|
||||
->get();
|
||||
->leftJoin('refunds', 'orders.id', 'refunds.order_id')
|
||||
->select(DB::raw("(SUM({$dbPrefix}orders.base_grand_total) - SUM(IFNULL({$dbPrefix}refunds.base_grand_total, 0))) as total_base_grand_total"))
|
||||
->addSelect(DB::raw("COUNT({$dbPrefix}orders.id) as total_orders"))
|
||||
->addSelect('orders.id', 'customer_id', 'customer_email', 'customer_first_name', 'customer_last_name')
|
||||
->where('orders.created_at', '>=', $this->startDate)
|
||||
->where('orders.created_at', '<=', $this->endDate)
|
||||
->where('orders.status', '<>', 'closed')
|
||||
->where('orders.status', '<>', 'canceled')
|
||||
->groupBy('customer_email')
|
||||
->orderBy('total_base_grand_total', 'DESC')
|
||||
->limit(5)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets start and end date
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setStartEndDate()
|
||||
{
|
||||
$this->startDate = request()->get('start')
|
||||
? Carbon::createFromTimeString(request()->get('start') . " 00:00:01")
|
||||
: Carbon::createFromTimeString(Carbon::now()->subDays(30)->format('Y-m-d') . " 00:00:01");
|
||||
|
||||
$this->endDate = request()->get('end')
|
||||
? Carbon::createFromTimeString(request()->get('end') . " 23:59:59")
|
||||
: Carbon::now();
|
||||
|
||||
if ($this->endDate > Carbon::now()) {
|
||||
$this->endDate = Carbon::now();
|
||||
}
|
||||
|
||||
$this->lastStartDate = clone $this->startDate;
|
||||
$this->lastEndDate = clone $this->startDate;
|
||||
|
||||
$this->lastStartDate->subDays($this->startDate->diffInDays($this->endDate));
|
||||
// $this->lastEndDate->subDays($this->lastStartDate->diffInDays($this->lastEndDate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns previous order query
|
||||
* Returns previous order query.
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
|
|
@ -289,7 +306,7 @@ class DashboardController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns current order query
|
||||
* Returns current order query.
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
|
|
@ -299,7 +316,7 @@ class DashboardController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns orders between two dates
|
||||
* Returns orders between two dates.
|
||||
*
|
||||
* @param \Illuminate\Support\Carbon $start
|
||||
* @param \Illuminate\Support\Carbon $end
|
||||
|
|
@ -313,16 +330,31 @@ class DashboardController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns customers between two dates
|
||||
* Returns customers between two dates.
|
||||
*
|
||||
* @param \Illuminate\Support\Carbon $start
|
||||
* @param \Illuminate\Support\Carbon $end
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
* @return int
|
||||
*/
|
||||
private function getCustomersBetweenDates($start, $end)
|
||||
{
|
||||
return $this->customerRepository->scopeQuery(function ($query) use ($start, $end) {
|
||||
return $query->where('customers.created_at', '>=', $start)->where('customers.created_at', '<=', $end);
|
||||
});
|
||||
return $this->customerRepository
|
||||
->where('customers.created_at', '>=', $start)
|
||||
->where('customers.created_at', '<=', $end)
|
||||
->count();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns total pending invoices between two dates.
|
||||
*
|
||||
* @param \Illuminate\Support\Carbon $start
|
||||
* @param \Illuminate\Support\Carbon $end
|
||||
* @return string
|
||||
*/
|
||||
private function getTotalPendingInvoices()
|
||||
{
|
||||
return $this->invoiceRepository
|
||||
->where('state', 'pending')
|
||||
->sum('grand_total');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace Webkul\Admin\Http\Controllers\Sales;
|
|||
|
||||
use PDF;
|
||||
use Webkul\Admin\Http\Controllers\Controller;
|
||||
use Webkul\Sales\Repositories\OrderRepository;
|
||||
use Webkul\Sales\Repositories\InvoiceRepository;
|
||||
use Webkul\Sales\Repositories\OrderRepository;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
|
|
@ -17,14 +17,14 @@ class InvoiceController extends Controller
|
|||
protected $_config;
|
||||
|
||||
/**
|
||||
* OrderRepository object
|
||||
* Order repository instance.
|
||||
*
|
||||
* @var \Webkul\Sales\Repositories\OrderRepository
|
||||
*/
|
||||
protected $orderRepository;
|
||||
|
||||
/**
|
||||
* InvoiceRepository object
|
||||
* Invoice repository instance.
|
||||
*
|
||||
* @var \Webkul\Sales\Repositories\InvoiceRepository
|
||||
*/
|
||||
|
|
@ -40,8 +40,7 @@ class InvoiceController extends Controller
|
|||
public function __construct(
|
||||
OrderRepository $orderRepository,
|
||||
InvoiceRepository $invoiceRepository
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->middleware('admin');
|
||||
|
||||
$this->_config = request('_config');
|
||||
|
|
@ -71,6 +70,10 @@ class InvoiceController extends Controller
|
|||
{
|
||||
$order = $this->orderRepository->findOrFail($orderId);
|
||||
|
||||
if ($order->payment->method === 'paypal_standard') {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return view($this->_config['view'], compact('order'));
|
||||
}
|
||||
|
||||
|
|
@ -160,9 +163,9 @@ class InvoiceController extends Controller
|
|||
|
||||
$p = $arabic->arIdentify($html);
|
||||
|
||||
for ($i = count($p)-1; $i >= 0; $i -= 2) {
|
||||
$utf8ar = $arabic->utf8Glyphs(substr($html, $p[$i-1], $p[$i] - $p[$i-1]));
|
||||
$html = substr_replace($html, $utf8ar, $p[$i-1], $p[$i] - $p[$i-1]);
|
||||
for ($i = count($p) - 1; $i >= 0; $i -= 2) {
|
||||
$utf8ar = $arabic->utf8Glyphs(substr($html, $p[$i - 1], $p[$i] - $p[$i - 1]));
|
||||
$html = substr_replace($html, $utf8ar, $p[$i - 1], $p[$i] - $p[$i - 1]);
|
||||
}
|
||||
|
||||
return $html;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
/**
|
||||
* Main imports.
|
||||
*/
|
||||
import Vue from 'vue';
|
||||
import VeeValidate, { Validator } from 'vee-validate';
|
||||
import VeeValidate from 'vee-validate';
|
||||
import './bootstrap';
|
||||
|
||||
/**
|
||||
* Lang imports.
|
||||
*/
|
||||
import de from 'vee-validate/dist/locale/de';
|
||||
import ar from 'vee-validate/dist/locale/ar';
|
||||
import fa from 'vee-validate/dist/locale/fa';
|
||||
|
|
@ -7,39 +15,50 @@ import fr from 'vee-validate/dist/locale/fr';
|
|||
import nl from 'vee-validate/dist/locale/nl';
|
||||
import tr from 'vee-validate/dist/locale/tr';
|
||||
|
||||
|
||||
import './bootstrap';
|
||||
|
||||
window.Vue = Vue;
|
||||
window.VeeValidate = VeeValidate;
|
||||
|
||||
/**
|
||||
* Vue plugins.
|
||||
*/
|
||||
Vue.use(VeeValidate, {
|
||||
dictionary: {
|
||||
ar: ar,
|
||||
de: de,
|
||||
fa: fa,
|
||||
fr: fr,
|
||||
nl: nl,
|
||||
tr: tr,
|
||||
fa: fa,
|
||||
fr: fr,
|
||||
nl: nl,
|
||||
tr: tr
|
||||
},
|
||||
events: 'input|change|blur',
|
||||
events: 'input|change|blur'
|
||||
});
|
||||
Vue.prototype.$http = axios
|
||||
|
||||
Vue.component('nav-slide-button', require('./components/navigation/nav-slide-button').default);
|
||||
Vue.component('required-if', require('./components/validators/required-if').default);
|
||||
/**
|
||||
* Vue prototype.
|
||||
*/
|
||||
Vue.prototype.$http = axios;
|
||||
|
||||
/**
|
||||
* Window assignation.
|
||||
*/
|
||||
window.Vue = Vue;
|
||||
window.eventBus = new Vue();
|
||||
window.VeeValidate = VeeValidate;
|
||||
|
||||
$(document).ready(function () {
|
||||
Vue.config.ignoredElements = [
|
||||
'option-wrapper',
|
||||
'group-form',
|
||||
'group-list'
|
||||
];
|
||||
/**
|
||||
* Global components.
|
||||
*/
|
||||
Vue.component(
|
||||
'nav-slide-button',
|
||||
require('./components/navigation/nav-slide-button').default
|
||||
);
|
||||
Vue.component(
|
||||
'required-if',
|
||||
require('./components/validators/required-if').default
|
||||
);
|
||||
|
||||
var app = new Vue({
|
||||
el: "#app",
|
||||
$(function() {
|
||||
Vue.config.ignoredElements = ['option-wrapper', 'group-form', 'group-list'];
|
||||
|
||||
let app = new Vue({
|
||||
el: '#app',
|
||||
|
||||
data: {
|
||||
modalIds: {}
|
||||
|
|
@ -47,54 +66,93 @@ $(document).ready(function () {
|
|||
|
||||
mounted() {
|
||||
this.addServerErrors();
|
||||
|
||||
this.addFlashMessages();
|
||||
|
||||
this.$validator.localize(document.documentElement.lang);
|
||||
},
|
||||
|
||||
methods: {
|
||||
onSubmit: function (e) {
|
||||
onSubmit: function(e) {
|
||||
this.toggleButtonDisable(true);
|
||||
|
||||
if(typeof tinyMCE !== 'undefined')
|
||||
tinyMCE.triggerSave();
|
||||
if (typeof tinyMCE !== 'undefined') tinyMCE.triggerSave();
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
e.target.submit();
|
||||
} else {
|
||||
this.activateAutoScroll();
|
||||
|
||||
this.toggleButtonDisable(false);
|
||||
|
||||
eventBus.$emit('onFormError')
|
||||
eventBus.$emit('onFormError');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggleButtonDisable (value) {
|
||||
var buttons = document.getElementsByTagName("button");
|
||||
activateAutoScroll: function() {
|
||||
/**
|
||||
* This is accordion element.
|
||||
*/
|
||||
const accordionElement = document.querySelector(
|
||||
'.accordian.error'
|
||||
);
|
||||
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
/**
|
||||
* This is normal element.
|
||||
*/
|
||||
const normalElement = document.querySelector(
|
||||
'.control-error:first-of-type'
|
||||
);
|
||||
|
||||
/**
|
||||
* Scroll configs.
|
||||
*/
|
||||
const scrollConfigs = {
|
||||
behavior: 'smooth',
|
||||
block: 'end',
|
||||
inline: 'nearest'
|
||||
};
|
||||
|
||||
/**
|
||||
* If accordion error is not found then scroll will fall to the normal element.
|
||||
*/
|
||||
if (accordionElement) {
|
||||
accordionElement.scrollIntoView(scrollConfigs);
|
||||
return;
|
||||
}
|
||||
|
||||
normalElement.scrollIntoView(scrollConfigs);
|
||||
},
|
||||
|
||||
toggleButtonDisable: function(value) {
|
||||
let buttons = document.getElementsByTagName('button');
|
||||
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
buttons[i].disabled = value;
|
||||
}
|
||||
},
|
||||
|
||||
addServerErrors(scope = null) {
|
||||
for (var key in serverErrors) {
|
||||
var inputNames = [];
|
||||
key.split('.').forEach(function(chunk, index) {
|
||||
if(index) {
|
||||
inputNames.push('[' + chunk + ']')
|
||||
} else {
|
||||
inputNames.push(chunk)
|
||||
}
|
||||
})
|
||||
addServerErrors: function(scope = null) {
|
||||
for (let key in serverErrors) {
|
||||
let inputNames = [];
|
||||
|
||||
var inputName = inputNames.join('');
|
||||
key.split('.').forEach(function(chunk, index) {
|
||||
if (index) {
|
||||
inputNames.push('[' + chunk + ']');
|
||||
} else {
|
||||
inputNames.push(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
let inputName = inputNames.join('');
|
||||
|
||||
const field = this.$validator.fields.find({
|
||||
name: inputName,
|
||||
scope: scope
|
||||
});
|
||||
|
||||
if (field) {
|
||||
this.$validator.errors.add({
|
||||
id: field.id,
|
||||
|
|
@ -106,10 +164,10 @@ $(document).ready(function () {
|
|||
}
|
||||
},
|
||||
|
||||
addFlashMessages() {
|
||||
addFlashMessages: function() {
|
||||
if (typeof flashMessages == 'undefined') {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
const flashes = this.$refs.flashes;
|
||||
|
||||
|
|
@ -118,7 +176,7 @@ $(document).ready(function () {
|
|||
}, this);
|
||||
},
|
||||
|
||||
showModal(id) {
|
||||
showModal: function(id) {
|
||||
this.$set(this.modalIds, id, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ return [
|
|||
'total-orders' => 'مجموع الطلبات',
|
||||
'total-sale' => 'مجموع المبيعات',
|
||||
'average-sale' => 'متوسط مبيعات الطلبات',
|
||||
'total-unpaid-invoices' => 'إجمالي الفواتير غير المسددة',
|
||||
'increased' => ':progress% زيادة',
|
||||
'decreased' => ':progress% نقصان',
|
||||
'sales' => 'المبيعات',
|
||||
|
|
@ -970,11 +971,11 @@ return [
|
|||
'create-btn-title' => 'اضف عنوان',
|
||||
'save-btn-title' => 'حفظ العنوان',
|
||||
'general' => 'جنرال لواء',
|
||||
'success-create' => 'تم إنشاء عنوان العميل بنجاح Success:',
|
||||
'success-update' => 'تم تحديث عنوان العميل بنجاح Success:',
|
||||
'success-delete' => 'تم حذف عنوان العميل بنجاح Success:',
|
||||
'success-mass-delete' => 'تم حذف العناوين المحددة بنجاح Success:',
|
||||
'error-create' => 'لم يتم إنشاء عنوان العميل Error:',
|
||||
'success-create' => 'تم إنشاء عنوان العميل بنجاح',
|
||||
'success-update' => 'تم تحديث عنوان العميل بنجاح',
|
||||
'success-delete' => 'تم حذف عنوان العميل بنجاح',
|
||||
'success-mass-delete' => 'تم حذف العناوين المحددة بنجاح',
|
||||
'error-create' => 'لم يتم إنشاء عنوان العميل',
|
||||
],
|
||||
|
||||
'note' => [
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ return [
|
|||
'total-orders' => 'Anzahl Aufträge',
|
||||
'total-sale' => 'Gesamterlös',
|
||||
'average-sale' => 'Durchschnitt pro Verkauf',
|
||||
'total-unpaid-invoices' => 'Gesamtzahl unbezahlter Rechnungen',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Vertrieb',
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ return [
|
|||
'total-orders' => 'Total Orders',
|
||||
'total-sale' => 'Total Sale',
|
||||
'average-sale' => 'Average Order Sale',
|
||||
'total-unpaid-invoices' => 'Total Unpaid Invoices',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Sales',
|
||||
|
|
@ -978,11 +979,11 @@ return [
|
|||
'create-btn-title' => 'Add Address',
|
||||
'save-btn-title' => 'Save Address',
|
||||
'general' => 'General',
|
||||
'success-create' => 'Success: Customer address created successfully.',
|
||||
'success-update' => 'Success: Customer address updated successfully.',
|
||||
'success-delete' => 'Success: Customer address deleted successfully.',
|
||||
'success-mass-delete' => 'Success: selected addresses deleted successfully.',
|
||||
'error-create' => 'Error: Customer address not created.',
|
||||
'success-create' => 'Customer address created successfully.',
|
||||
'success-update' => 'Customer address updated successfully.',
|
||||
'success-delete' => 'Customer address deleted successfully.',
|
||||
'success-mass-delete' => 'Selected addresses deleted successfully.',
|
||||
'error-create' => 'Customer address not created.',
|
||||
],
|
||||
|
||||
'note' => [
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ return [
|
|||
'total-orders' => 'Total Pedidos',
|
||||
'total-sale' => 'Total Ventas',
|
||||
'average-sale' => 'Promedio de pedidos vendidos',
|
||||
'total-unpaid-invoices' => 'Facturas impagas totales',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Ventas',
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@ return [
|
|||
'marketing' => 'بازاریابی',
|
||||
'promotions' => 'تبلیغات',
|
||||
'email-marketing' => 'بازاریابی ایمیل',
|
||||
'campaigns' => 'Campaigns',
|
||||
'campaigns' => 'کمپین ها',
|
||||
'email-templates' => 'قالب های ایمیل',
|
||||
'discount' => 'تخفیف',
|
||||
'cms' => 'CMS',
|
||||
'cms' => 'مدیری محتوا',
|
||||
'transactions' => 'پرداختی ها',
|
||||
'events' => 'رویداد ها'
|
||||
],
|
||||
|
|
@ -100,7 +100,7 @@ return [
|
|||
'attributes' => 'ویژگی ها',
|
||||
'attribute-families' => 'نوع ویژگی',
|
||||
'customers' => 'مشتریان',
|
||||
'addresses' => 'Addresses',
|
||||
'addresses' => 'آدرس ها',
|
||||
'note' => 'Note',
|
||||
'groups' => 'گروه ها',
|
||||
'reviews' => 'بررسی ها',
|
||||
|
|
@ -122,8 +122,8 @@ return [
|
|||
'edit' => 'ویاریش',
|
||||
'create' => 'افزودن',
|
||||
'delete' => 'حذف',
|
||||
'mass-delete' => 'Mass Delete',
|
||||
'mass-update' => 'Mass Update',
|
||||
'mass-delete' => 'حذف دسته ای',
|
||||
'mass-update' => 'آپدیت دسته ای',
|
||||
'marketing' => 'بازاریابی',
|
||||
'promotions' => 'تبلیغات',
|
||||
'cart-rules' => 'قوانین سبد خرید',
|
||||
|
|
@ -138,6 +138,7 @@ return [
|
|||
'total-orders' => 'همه سفارشات',
|
||||
'total-sale' => 'مجموع فروش',
|
||||
'average-sale' => 'میانگین فروش',
|
||||
'total-unpaid-invoices' => 'مجموع فاکتورهای پرداخت نشده',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'فروش ها',
|
||||
|
|
@ -149,7 +150,7 @@ return [
|
|||
'order-count' => 'سفارش :count',
|
||||
'revenue' => ':total درآمد',
|
||||
'stock-threshold' => 'تعداد کالای موجود',
|
||||
'qty-left' => ':qty سمت چپ',
|
||||
'qty-left' => ':qty باقی مانده',
|
||||
],
|
||||
|
||||
'datagrid' => [
|
||||
|
|
@ -574,12 +575,12 @@ return [
|
|||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'New Option',
|
||||
'is-default' => 'Is Default',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
'remove-image-btn-title' => 'حذف عکس',
|
||||
'videos' => 'فیلم ها',
|
||||
'video' => 'فیلم',
|
||||
'add-video-btn-title' => 'اضافه کردن فیلم',
|
||||
'remove-video-btn-title' => 'حذف فیلم',
|
||||
'not-support-video' => 'مرورگر شما تگ ویدیو را پشتیبانی نمی کند',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
@ -592,7 +593,7 @@ return [
|
|||
'type' => 'نوع ویژگی',
|
||||
'text' => 'Text',
|
||||
'textarea' => 'Textarea',
|
||||
'price' => 'Price',
|
||||
'price' => 'قیمت',
|
||||
'boolean' => 'Boolean',
|
||||
'select' => 'Select',
|
||||
'multiselect' => 'Multiselect',
|
||||
|
|
@ -966,10 +967,10 @@ return [
|
|||
'create-btn-title' => 'اضافه کردن آدرس',
|
||||
'save-btn-title' => 'ذخیره آدرس',
|
||||
'general' => 'عمومی',
|
||||
'success-create' => 'آدرس مشتری با موفقیت ایجاد شد Success:',
|
||||
'success-update' => 'آدرس مشتری با موفقیت به روز شد Success:',
|
||||
'success-delete' => 'آدرس مشتری با موفقیت حذف شد Success:',
|
||||
'success-mass-delete' => 'آدرس های انتخاب شده با موفقیت حذف شدند Success:',
|
||||
'success-create' => 'آدرس مشتری با موفقیت ایجاد شد ',
|
||||
'success-update' => 'آدرس مشتری با موفقیت به روز شد ',
|
||||
'success-delete' => 'آدرس مشتری با موفقیت حذف شد ',
|
||||
'success-mass-delete' => 'آدرس های انتخاب شده با موفقیت حذف شدند ',
|
||||
'error-create' => 'آدرس مشتری ایجاد نشده است Error:',
|
||||
],
|
||||
|
||||
|
|
@ -1031,6 +1032,11 @@ return [
|
|||
'update-failed' => 'خطا! شما نمی توانید مشترک مشترک شوید',
|
||||
'delete' => 'مشترک با موفقیت حذف شد',
|
||||
'delete-failed' => 'خطا! مشترک نمی تواند حذف شود'
|
||||
],
|
||||
|
||||
'orders' => [
|
||||
'list' => ':customer_name\'s orders List',
|
||||
'title' => 'سفارشات'
|
||||
]
|
||||
],
|
||||
|
||||
|
|
@ -1068,7 +1074,7 @@ return [
|
|||
'choose-condition-to-add' => 'شرطی را برای اضافه کردن انتخاب کنید',
|
||||
'cart-attribute' => 'ویژگی سبد خرید',
|
||||
'subtotal' => 'جمع جز',
|
||||
'additional' => 'Additional Information',
|
||||
'additional' => 'اطلاعات تکمیلی',
|
||||
'total-items-qty' => 'تعداد کل موارد',
|
||||
'total-weight' => 'وزن کل',
|
||||
'payment-method' => 'روش پرداخت',
|
||||
|
|
@ -1122,7 +1128,7 @@ return [
|
|||
],
|
||||
|
||||
'catalog-rules' => [
|
||||
'title' => 'قوانین فهرست',
|
||||
'title' => 'قوانین کاتالوگ',
|
||||
'add-title' => 'اضافه کردن قانون جدید',
|
||||
'edit-title' => 'تنظیم قانون کاتالوگ',
|
||||
'save-btn-title' => 'ذخیره قانون کاتالوگ',
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ return [
|
|||
'total-orders' => 'Total des commandes',
|
||||
'total-sale' => 'Vente totale',
|
||||
'average-sale' => 'Vente de commande moyenne',
|
||||
'total-unpaid-invoices' => 'Total des factures impayées',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Ventes',
|
||||
|
|
@ -166,7 +167,7 @@ return [
|
|||
'update-success' => 'Sélectionné :resource a été mise à jour avec succès',
|
||||
'no-resource' => 'La ressource prévue est insuffisante pour l\'action',
|
||||
],
|
||||
|
||||
|
||||
'id' => 'identifiant',
|
||||
'status' => 'Statut',
|
||||
'code' => 'Code',
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ return [
|
|||
'total-orders' => 'Totale Ordini',
|
||||
'total-sale' => 'Totale Vendite',
|
||||
'average-sale' => 'Media Ordine di Vendita',
|
||||
'total-unpaid-invoices' => 'Totale fatture non pagate',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Vendite',
|
||||
|
|
@ -972,11 +973,11 @@ return [
|
|||
'create-btn-title' => 'Aggiungi Indirizzo',
|
||||
'save-btn-title' => 'Salva Indirizzo',
|
||||
'general' => 'Generale',
|
||||
'success-create' => 'Success: Indirizzo cliente creato con successo.',
|
||||
'success-update' => 'Success: Indirizzo cliente aggiornato con successo.',
|
||||
'success-delete' => 'Success: Indirizzo cliente eliminato con successo.',
|
||||
'success-mass-delete' => 'Success: indirizzi selezionati eliminati con successo.',
|
||||
'error-create' => 'Error: Indirizzo cliente non creato.',
|
||||
'success-create' => 'Indirizzo cliente creato con successo.',
|
||||
'success-update' => 'Indirizzo cliente aggiornato con successo.',
|
||||
'success-delete' => 'Indirizzo cliente eliminato con successo.',
|
||||
'success-mass-delete' => 'indirizzi selezionati eliminati con successo.',
|
||||
'error-create' => 'Indirizzo cliente non creato.',
|
||||
],
|
||||
|
||||
'note' => [
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ return [
|
|||
'total-orders' => 'Totaal aantal bestellingen',
|
||||
'total-sale' => 'Verkooptotaal',
|
||||
'average-sale' => 'Gemiddelde orderwaarde',
|
||||
'total-unpaid-invoices' => 'Totaal onbetaalde facturen',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Verkopen',
|
||||
|
|
@ -967,10 +968,10 @@ return [
|
|||
'create-btn-title' => 'Adres toevoegen',
|
||||
'save-btn-title' => 'Bewaar adres',
|
||||
'general' => 'Algemeen',
|
||||
'success-create' => 'Success: Klantadres succesvol aangemaakt.',
|
||||
'success-update' => 'Success: Klantadres succesvol bijgewerkt.',
|
||||
'success-delete' => 'Success: Klantadres succesvol verwijderd.',
|
||||
'success-mass-delete' => 'Success: geselecteerde adressen zijn succesvol verwijderd.',
|
||||
'success-create' => 'Klantadres succesvol aangemaakt.',
|
||||
'success-update' => 'Klantadres succesvol bijgewerkt.',
|
||||
'success-delete' => 'Klantadres succesvol verwijderd.',
|
||||
'success-mass-delete' => 'geselecteerde adressen zijn succesvol verwijderd.',
|
||||
'error-create' => 'Error: Klantadres niet aangemaakt.',
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ return [
|
|||
'total-orders' => 'Zamówienia ogółem',
|
||||
'total-sale' => 'Całkowita sprzedaż',
|
||||
'average-sale' => 'Średnia sprzedaż na zamówienie',
|
||||
'total-unpaid-invoices' => 'Łącznie nieopłacone faktury',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Sprzedaż',
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ return [
|
|||
'total-orders' => 'Total de Pedidos',
|
||||
'total-sale' => 'Total de Vendas',
|
||||
'average-sale' => 'Média por Pedido',
|
||||
'total-unpaid-invoices' => 'Total de faturas não pagas',
|
||||
'increased' => ':progress% AumentoMai',
|
||||
'decreased' => ':progress% Redução',
|
||||
'sales' => 'Vendas',
|
||||
|
|
@ -969,10 +970,10 @@ return [
|
|||
'create-btn-title' => 'Adicionar endereço',
|
||||
'save-btn-title' => 'Salvar endereço',
|
||||
'general' => 'Geral',
|
||||
'success-create' => 'Success: Endereço do cliente criado com sucesso.',
|
||||
'success-update' => 'Success: Endereço do cliente atualizado com sucesso.',
|
||||
'success-delete' => 'Success: Endereço do cliente excluído com sucesso.',
|
||||
'success-mass-delete' => 'Success: endereços selecionados excluídos com sucesso.',
|
||||
'success-create' => 'Endereço do cliente criado com sucesso.',
|
||||
'success-update' => 'Endereço do cliente atualizado com sucesso.',
|
||||
'success-delete' => 'Endereço do cliente excluído com sucesso.',
|
||||
'success-mass-delete' => 'endereços selecionados excluídos com sucesso.',
|
||||
'error-create' => 'Error: Endereço do cliente não criado.',
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ return [
|
|||
'total-orders' => 'Tplam Sipariş',
|
||||
'total-sale' => 'Tplam Satış',
|
||||
'average-sale' => 'Ortalama Satış',
|
||||
'total-unpaid-invoices' => 'Toplam Ödenmemiş Faturalar',
|
||||
'increased' => ':progress%',
|
||||
'decreased' => ':progress%',
|
||||
'sales' => 'Satış',
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@
|
|||
{!! view_render_event('bagisto.admin.catalog.category.edit_form_accordian.general.controls.before', ['category' => $category]) !!}
|
||||
|
||||
<div class="control-group" :class="[errors.has('{{$locale}}[name]') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.catalog.categories.name') }}</label>
|
||||
<label for="name" class="required">{{ __('admin::app.catalog.categories.name') }}
|
||||
<span class="locale">[{{ $locale }}]</span>
|
||||
</label>
|
||||
<input type="text" v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" value="{{ old($locale)['name'] ?? ($category->translate($locale)['name'] ?? '') }}" data-vv-as=""{{ __('admin::app.catalog.categories.name') }}"" v-slugify-target="'slug'"/>
|
||||
<span class="control-error" v-if="errors.has('{{$locale}}[name]')">@{{ errors.first('{!!$locale!!}[name]') }}</span>
|
||||
</div>
|
||||
|
|
@ -181,23 +183,31 @@
|
|||
{!! view_render_event('bagisto.admin.catalog.category.edit_form_accordian.seo.controls.before', ['category' => $category]) !!}
|
||||
|
||||
<div class="control-group">
|
||||
<label for="meta_title">{{ __('admin::app.catalog.categories.meta_title') }}</label>
|
||||
<label for="meta_title">{{ __('admin::app.catalog.categories.meta_title') }}
|
||||
<span class="locale">[{{ $locale }}]</span>
|
||||
</label>
|
||||
<input type="text" class="control" id="meta_title" name="{{$locale}}[meta_title]" value="{{ old($locale)['meta_title'] ?? ($category->translate($locale)['meta_title'] ?? '') }}"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('{{$locale}}[slug]') ? 'has-error' : '']">
|
||||
<label for="slug" class="required">{{ __('admin::app.catalog.categories.slug') }}</label>
|
||||
<label for="slug" class="required">{{ __('admin::app.catalog.categories.slug') }}
|
||||
<span class="locale">[{{ $locale }}]</span>
|
||||
</label>
|
||||
<input type="text" v-validate="'required'" class="control" id="slug" name="{{$locale}}[slug]" value="{{ old($locale)['slug'] ?? ($category->translate($locale)['slug'] ?? '') }}" data-vv-as=""{{ __('admin::app.catalog.categories.slug') }}"" v-slugify/>
|
||||
<span class="control-error" v-if="errors.has('{{$locale}}[slug]')">@{{ errors.first('{!!$locale!!}[slug]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="meta_description">{{ __('admin::app.catalog.categories.meta_description') }}</label>
|
||||
<label for="meta_description">{{ __('admin::app.catalog.categories.meta_description') }}
|
||||
<span class="locale">[{{ $locale }}]</span>
|
||||
</label>
|
||||
<textarea class="control" id="meta_description" name="{{$locale}}[meta_description]">{{ old($locale)['meta_description'] ?? ($category->translate($locale)['meta_description'] ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="meta_keywords">{{ __('admin::app.catalog.categories.meta_keywords') }}</label>
|
||||
<label for="meta_keywords">{{ __('admin::app.catalog.categories.meta_keywords') }}
|
||||
<span class="locale">[{{ $locale }}]</span>
|
||||
</label>
|
||||
<textarea class="control" id="meta_keywords" name="{{$locale}}[meta_keywords]">{{ old($locale)['meta_keywords'] ?? ($category->translate($locale)['meta_keywords'] ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
|
|
@ -221,7 +231,9 @@
|
|||
<script type="text/x-template" id="description-template">
|
||||
|
||||
<div class="control-group" :class="[errors.has('{{$locale}}[description]') ? 'has-error' : '']">
|
||||
<label for="description" :class="isRequired ? 'required' : ''">{{ __('admin::app.catalog.categories.description') }}</label>
|
||||
<label for="description" :class="isRequired ? 'required' : ''">{{ __('admin::app.catalog.categories.description') }}
|
||||
<span class="locale">[{{ $locale }}]</span>
|
||||
</label>
|
||||
<textarea v-validate="isRequired ? 'required' : ''" class="control" id="description" name="{{$locale}}[description]" data-vv-as=""{{ __('admin::app.catalog.categories.description') }}"">{{ old($locale)['description'] ?? ($category->translate($locale)['description'] ?? '') }}</textarea>
|
||||
<span class="control-error" v-if="errors.has('{{$locale}}[description]')">@{{ errors.first('{!!$locale!!}[description]') }}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@php($locale = core()->getRequestedLocaleCode())
|
||||
|
||||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
|
|
@ -16,12 +18,27 @@
|
|||
{{ __('admin::app.catalog.categories.add-title') }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<select class="control" id="locale-switcher" name="locale"
|
||||
onchange="reloadPage('locale', this.value)">
|
||||
<option value="all" {{ ! isset($locale) ? 'selected' : '' }}>
|
||||
{{ __('admin::app.admin.system.all-locales') }}
|
||||
</option>
|
||||
@foreach (core()->getAllLocales() as $localeModel)
|
||||
<option
|
||||
value="{{ $localeModel->code }}" {{ (isset($locale) && ($localeModel->code) == $locale) ? 'selected' : '' }}>
|
||||
{{ $localeModel->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.categories.list.before') !!}
|
||||
|
||||
<div class="page-content">
|
||||
{!! app('Webkul\Admin\DataGrids\CategoryDataGrid')->render() !!}
|
||||
@inject('categories', 'Webkul\Admin\DataGrids\CategoryDataGrid')
|
||||
{!! $categories->render() !!}
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.categories.list.after') !!}
|
||||
|
|
@ -30,6 +47,13 @@
|
|||
|
||||
@push('scripts')
|
||||
<script>
|
||||
function reloadPage(getVar, getVal) {
|
||||
let url = new URL(window.location.href);
|
||||
url.searchParams.set(getVar, getVal);
|
||||
|
||||
window.location.href = url.href;
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$("input[type='checkbox']").change(deleteFunction);
|
||||
});
|
||||
|
|
@ -47,7 +71,7 @@
|
|||
|
||||
var indexes = formData.indexes;
|
||||
}
|
||||
|
||||
|
||||
if (indexes) {
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
|
|
|
|||
|
|
@ -125,6 +125,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-card">
|
||||
<div class="title">
|
||||
{{ __('admin::app.dashboard.total-unpaid-invoices') }}
|
||||
</div>
|
||||
|
||||
<div class="data">
|
||||
{{ core()->formatBasePrice($statistics['total_unpaid_invoices']) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="graph-stats">
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
</a>
|
||||
@endif
|
||||
|
||||
@if ($order->canInvoice())
|
||||
@if ($order->canInvoice() && $order->payment->method !== 'paypal_standard')
|
||||
<a href="{{ route('admin.sales.invoices.create', $order->id) }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.sales.orders.invoice-btn-title') }}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,9 @@ class Cart
|
|||
$cart->discount_amount = round($cart->discount_amount, 2);
|
||||
$cart->base_discount_amount = round($cart->base_discount_amount, 2);
|
||||
|
||||
$cart->grand_total = round($cart->grand_total, 2);
|
||||
$cart->sub_total = round($cart->sub_total, 2);
|
||||
$cart->base_sub_total = round($cart->base_sub_total, 2);
|
||||
|
||||
$cart->grand_total = round($cart->grand_total, 2);
|
||||
$cart->base_grand_total = round($cart->base_grand_total, 2);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,22 @@ use Webkul\Core\Repositories\SliderRepository;
|
|||
class SliderController extends Controller
|
||||
{
|
||||
/**
|
||||
* Contains route related configuration
|
||||
* Contains route related configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* SliderRepository
|
||||
* Slider repository instance.
|
||||
*
|
||||
* @var \Webkul\Core\Repositories\SliderRepository
|
||||
*/
|
||||
protected $sliderRepository;
|
||||
|
||||
/**
|
||||
* Channels.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $channels;
|
||||
|
|
@ -61,7 +63,7 @@ class SliderController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates the new sider item.
|
||||
* Creates the new slider item.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
|
|
@ -75,6 +77,7 @@ class SliderController extends Controller
|
|||
]);
|
||||
|
||||
$data = request()->all();
|
||||
|
||||
$data['expired_at'] = $data['expired_at'] ?: null;
|
||||
|
||||
if (isset($data['locale'])) {
|
||||
|
|
@ -120,13 +123,14 @@ class SliderController extends Controller
|
|||
]);
|
||||
|
||||
$data = request()->all();
|
||||
|
||||
$data['expired_at'] = $data['expired_at'] ?: null;
|
||||
|
||||
if (isset($data['locale'])) {
|
||||
$data['locale'] = implode(',', $data['locale']);
|
||||
}
|
||||
|
||||
if ( is_null(request()->image)) {
|
||||
if (is_null(request()->image)) {
|
||||
session()->flash('error', trans('admin::app.settings.sliders.update-fail'));
|
||||
|
||||
return redirect()->back();
|
||||
|
|
@ -144,14 +148,14 @@ class SliderController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Delete a slider item and preserve the last one from deleting
|
||||
* Delete the slider item and preserve the last one from deleting.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$slider = $this->sliderRepository->findOrFail($id);
|
||||
$this->sliderRepository->findOrFail($id);
|
||||
|
||||
try {
|
||||
$this->sliderRepository->delete($id);
|
||||
|
|
@ -159,10 +163,10 @@ class SliderController extends Controller
|
|||
session()->flash('success', trans('admin::app.response.delete-success', ['name' => 'Slider']));
|
||||
|
||||
return response()->json(['message' => true], 200);
|
||||
} catch(\Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Slider']));
|
||||
}
|
||||
|
||||
return response()->json(['message' => false], 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Core\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class SecureHeaders
|
||||
{
|
||||
/**
|
||||
* Unwanted header list.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $unwantedHeaderList = [
|
||||
'X-Powered-By',
|
||||
'Server',
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$this->removeUnwantedHeaders();
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
$this->setHeaders($response);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set headers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function setHeaders($response)
|
||||
{
|
||||
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
|
||||
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
||||
$response->headers->set('X-XSS-Protection', '1; mode=block');
|
||||
$response->headers->set('X-Frame-Options', 'DENY');
|
||||
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unwanted headers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnwantedHeaders()
|
||||
{
|
||||
foreach ($this->unwantedHeaderList as $header) {
|
||||
header_remove($header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,9 @@ class Wishlist
|
|||
{
|
||||
$wishlist = false;
|
||||
|
||||
if ($customer = auth()->guard('customer')->user()) {
|
||||
$guard = request()->has('token') ? 'api' : 'customer';
|
||||
|
||||
if ($customer = auth()->guard($guard)->user()) {
|
||||
$wishlist = $customer->wishlist_items->filter(function ($item) use ($product) {
|
||||
return $item->channel_id == core()->getCurrentChannel()->id && $item->product_id == $product->product_id;
|
||||
})->first();
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ namespace Webkul\Marketing\Helpers;
|
|||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Webkul\Marketing\Repositories\EventRepository;
|
||||
use Webkul\Marketing\Repositories\CampaignRepository;
|
||||
use Webkul\Marketing\Repositories\TemplateRepository;
|
||||
use Webkul\Core\Models\SubscribersList;
|
||||
use Webkul\Marketing\Mail\NewsletterMail;
|
||||
use Webkul\Marketing\Repositories\CampaignRepository;
|
||||
use Webkul\Marketing\Repositories\EventRepository;
|
||||
|
||||
class Campaign
|
||||
{
|
||||
|
|
@ -45,8 +45,7 @@ class Campaign
|
|||
EventRepository $eventRepository,
|
||||
CampaignRepository $campaignRepository,
|
||||
CampaignRepository $templateRepository
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->eventRepository = $eventRepository;
|
||||
|
||||
$this->campaignRepository = $campaignRepository;
|
||||
|
|
@ -55,6 +54,8 @@ class Campaign
|
|||
}
|
||||
|
||||
/**
|
||||
* Process the email.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process(): void
|
||||
|
|
@ -85,43 +86,35 @@ class Campaign
|
|||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
* Get the email address.
|
||||
*
|
||||
* @param \Webkul\Marketing\Contracts\Campaign $campaign
|
||||
* @return array
|
||||
*/
|
||||
public function getEmailAddresses($campaign)
|
||||
{
|
||||
$emails = [];
|
||||
|
||||
$customerGroupEmails = $campaign->customer_group->customers()->where('subscribed_to_news_letter', 1)->get('email');
|
||||
|
||||
foreach ($customerGroupEmails as $row) {
|
||||
$emails[] = $row->email;
|
||||
if ($campaign->customer_group->code === 'guest') {
|
||||
$customerGroupEmails = SubscribersList::whereNull('customer_id');
|
||||
} else {
|
||||
$customerGroupEmails = $campaign->customer_group->customers()->where('subscribed_to_news_letter', 1);
|
||||
}
|
||||
|
||||
return array_unique($emails);
|
||||
return array_unique($customerGroupEmails->pluck('email')->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return customer's emails who has a birthday today
|
||||
* Return customer's emails who has a birthday today.
|
||||
*
|
||||
* @param \Webkul\Marketing\Contracts\Campaign $campaign
|
||||
* @return array
|
||||
*/
|
||||
public function getBirthdayEmails($campaign)
|
||||
{
|
||||
$customerGroupEmails = $campaign->customer_group->customers()
|
||||
return $campaign->customer_group
|
||||
->customers()
|
||||
->whereRaw('DATE_FORMAT(date_of_birth, "%m-%d") = ?', [Carbon::now()->format('m-d')])
|
||||
->where('subscribed_to_news_letter', 1)
|
||||
->get('email');
|
||||
|
||||
$emails = [];
|
||||
|
||||
foreach ($customerGroupEmails as $row) {
|
||||
$emails[] = $row->email;
|
||||
}
|
||||
|
||||
return $emails;
|
||||
->pluck('email')
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ return [
|
|||
], [
|
||||
'title' => 'admin::app.sales.invoices.status-paid',
|
||||
'value' => 'paid'
|
||||
],
|
||||
]
|
||||
],
|
||||
'info' => 'admin::app.admin.system.generate-invoice-applicable',
|
||||
'channel_based' => true,
|
||||
|
|
@ -137,10 +137,10 @@ return [
|
|||
'type' => 'select',
|
||||
'options' => [
|
||||
[
|
||||
'title' => 'Pending',
|
||||
'title' => 'admin::app.sales.invoices.status-pending',
|
||||
'value' => 'pending'
|
||||
], [
|
||||
'title' => 'Paid',
|
||||
'title' => 'admin::app.sales.invoices.status-paid',
|
||||
'value' => 'paid'
|
||||
]
|
||||
],
|
||||
|
|
@ -151,10 +151,13 @@ return [
|
|||
'type' => 'select',
|
||||
'options' => [
|
||||
[
|
||||
'title' => 'Pending',
|
||||
'title' => 'admin::app.sales.orders.order-status-pending',
|
||||
'value' => 'pending'
|
||||
], [
|
||||
'title' => 'Processing',
|
||||
'title' => 'admin::app.sales.orders.order-status-pending-payment',
|
||||
'value' => 'pending_payment'
|
||||
], [
|
||||
'title' => 'admin::app.sales.orders.order-status-processing',
|
||||
'value' => 'processing'
|
||||
]
|
||||
],
|
||||
|
|
|
|||
|
|
@ -8,16 +8,19 @@ use Intervention\Image\Filters\FilterInterface;
|
|||
class Large implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* Apply filter.
|
||||
*
|
||||
* @param \Intervention\Image\Image $image
|
||||
* @return \Intervention\Image\Image
|
||||
*/
|
||||
public function applyFilter(Image $image)
|
||||
{
|
||||
$width = core()->getConfigData('catalog.products.cache-large-image.width') ?? 480;
|
||||
$height = core()->getConfigData('catalog.products.cache-large-image.height') ?? 480;
|
||||
$width = core()->getConfigData('catalog.products.cache-large-image.width') != '' ? core()->getConfigData('catalog.products.cache-large-image.width') : 480;
|
||||
|
||||
$height = core()->getConfigData('catalog.products.cache-large-image.height') != '' ? core()->getConfigData('catalog.products.cache-large-image.height') : 480;
|
||||
|
||||
return $image->resize($width, $height, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,16 @@ use Intervention\Image\Filters\FilterInterface;
|
|||
class Medium implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* Apply filter.
|
||||
*
|
||||
* @param \Intervention\Image\Image $image
|
||||
* @return \Intervention\Image\Image
|
||||
*/
|
||||
public function applyFilter(Image $image)
|
||||
{
|
||||
$width = core()->getConfigData('catalog.products.cache-medium-image.width') ?? 280;
|
||||
$height = core()->getConfigData('catalog.products.cache-medium-image.height') ?? 280;
|
||||
$width = core()->getConfigData('catalog.products.cache-medium-image.width') != '' ? core()->getConfigData('catalog.products.cache-medium-image.width') : 280;
|
||||
|
||||
$height = core()->getConfigData('catalog.products.cache-medium-image.height') != '' ? core()->getConfigData('catalog.products.cache-medium-image.height') : 280;
|
||||
|
||||
$image->resize($width, $height, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
|
|
@ -22,4 +25,4 @@ class Medium implements FilterInterface
|
|||
|
||||
return $image->resizeCanvas($width, $height, 'center', false, '#fff');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,16 @@ use Intervention\Image\Filters\FilterInterface;
|
|||
class Small implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* Apply filter.
|
||||
*
|
||||
* @param \Intervention\Image\Image $image
|
||||
* @return \Intervention\Image\Image
|
||||
*/
|
||||
public function applyFilter(Image $image)
|
||||
{
|
||||
$width = core()->getConfigData('catalog.products.cache-small-image.width') ?? 120;
|
||||
$height = core()->getConfigData('catalog.products.cache-small-image.height') ?? 120;
|
||||
$width = core()->getConfigData('catalog.products.cache-small-image.width') ? core()->getConfigData('catalog.products.cache-small-image.width') : 120;
|
||||
|
||||
$height = core()->getConfigData('catalog.products.cache-small-image.height') ? core()->getConfigData('catalog.products.cache-small-image.height') : 120;
|
||||
|
||||
$image->resize($width, $height, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
|
|
@ -22,4 +25,4 @@ class Small implements FilterInterface
|
|||
|
||||
return $image->resizeCanvas($width, $height, 'center', false, '#fff');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,23 @@
|
|||
|
||||
namespace Webkul\Product\Type;
|
||||
|
||||
use Webkul\Tax\Helpers\Tax;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Checkout\Facades\Cart;
|
||||
use Webkul\Checkout\Models\CartItem;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Webkul\Customer\Repositories\CustomerGroupRepository;
|
||||
use Webkul\Inventory\Repositories\InventorySourceRepository;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Facades\ProductImage;
|
||||
use Webkul\Product\Models\ProductAttributeValue;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Tax\Repositories\TaxCategoryRepository;
|
||||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Customer\Repositories\CustomerGroupRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Inventory\Repositories\InventorySourceRepository;
|
||||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductCustomerGroupPriceRepository;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Tax\Helpers\Tax;
|
||||
use Webkul\Tax\Repositories\TaxCategoryRepository;
|
||||
|
||||
abstract class AbstractType
|
||||
{
|
||||
|
|
@ -565,7 +565,7 @@ abstract class AbstractType
|
|||
*/
|
||||
public function getFinalPrice($qty = null)
|
||||
{
|
||||
return $this->getMinimalPrice($qty);
|
||||
return round($this->getMinimalPrice($qty), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -801,9 +801,11 @@ abstract class AbstractType
|
|||
*/
|
||||
public function evaluatePrice($price)
|
||||
{
|
||||
$roundedOffPrice = round($price, 2);
|
||||
|
||||
return Tax::isTaxInclusive()
|
||||
? $this->getTaxInclusiveRate($price)
|
||||
: $price;
|
||||
? $this->getTaxInclusiveRate($roundedOffPrice)
|
||||
: $roundedOffPrice;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -938,7 +940,7 @@ abstract class AbstractType
|
|||
return $result;
|
||||
}
|
||||
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
$price = round($item->product->getTypeInstance()->getFinalPrice($item->quantity), 2);
|
||||
|
||||
if ($price == $item->base_price) {
|
||||
return $result;
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
namespace Webkul\Product\Type;
|
||||
|
||||
use Webkul\Checkout\Models\CartItem;
|
||||
use Webkul\Product\Helpers\BundleOption;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Checkout\Models\CartItem;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductBundleOptionRepository;
|
||||
use Webkul\Product\Helpers\BundleOption;
|
||||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductBundleOptionProductRepository;
|
||||
use Webkul\Product\Repositories\ProductBundleOptionRepository;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
|
||||
class Bundle extends AbstractType
|
||||
{
|
||||
|
|
@ -350,7 +350,7 @@ class Bundle extends AbstractType
|
|||
*/
|
||||
public function getFinalPrice($qty = null)
|
||||
{
|
||||
return 0;
|
||||
return round(0, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -712,6 +712,8 @@ class Bundle extends AbstractType
|
|||
$price += $childItem->base_price * $childItem->quantity;
|
||||
}
|
||||
|
||||
$price = round($price, 2);
|
||||
|
||||
if ($price == $item->base_price) {
|
||||
return $result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
namespace Webkul\Product\Type;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Product\Models\ProductFlat;
|
||||
use Webkul\Product\Facades\ProductImage;
|
||||
use Webkul\Product\Models\ProductAttributeValue;
|
||||
use Illuminate\Support\Str;
|
||||
use Webkul\Checkout\Models\CartItem as CartItemModel;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Facades\ProductImage;
|
||||
use Webkul\Product\Models\ProductAttributeValue;
|
||||
use Webkul\Product\Models\ProductFlat;
|
||||
|
||||
class Configurable extends AbstractType
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
namespace Webkul\Product\Type;
|
||||
|
||||
use Webkul\Checkout\Models\CartItem;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Checkout\Models\CartItem;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductDownloadableLinkRepository;
|
||||
use Webkul\Product\Repositories\ProductDownloadableSampleRepository;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
|
||||
class Downloadable extends AbstractType
|
||||
{
|
||||
|
|
@ -274,6 +274,8 @@ class Downloadable extends AbstractType
|
|||
$price += $link->price;
|
||||
}
|
||||
|
||||
$price = round($price, 2);
|
||||
|
||||
if ($price == $item->base_price) {
|
||||
return $result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ class Sequencer implements SequencerContract
|
|||
if ($this->length && ($this->prefix || $this->suffix)) {
|
||||
$number = ($this->prefix) . sprintf(
|
||||
"%0{$this->length}d",
|
||||
0
|
||||
) . ($this->lastId + 1) . ($this->suffix);
|
||||
($this->lastId + 1)
|
||||
) . ($this->suffix);
|
||||
} else {
|
||||
$number = $this->lastId + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ use Webkul\Sales\Contracts\ShipmentItem as ShipmentItemContract;
|
|||
|
||||
class ShipmentItem extends Model implements ShipmentItemContract
|
||||
{
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var string[]|bool
|
||||
*/
|
||||
protected $guarded = [
|
||||
'id',
|
||||
'child',
|
||||
|
|
@ -14,12 +19,17 @@ class ShipmentItem extends Model implements ShipmentItemContract
|
|||
'updated_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'additional' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Retrieve type instance
|
||||
* Retrieve type instance.
|
||||
*
|
||||
* @return AbstractType
|
||||
*/
|
||||
|
|
@ -27,7 +37,7 @@ class ShipmentItem extends Model implements ShipmentItemContract
|
|||
{
|
||||
return $this->order_item->getTypeInstance();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the shipment record associated with the shipment item.
|
||||
*/
|
||||
|
|
@ -53,18 +63,10 @@ class ShipmentItem extends Model implements ShipmentItemContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the child item record associated with the shipment item.
|
||||
*/
|
||||
public function child()
|
||||
{
|
||||
return $this->belongsTo(ShipmentItemProxy::modelClass(), 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get order item type
|
||||
* Get order item type.
|
||||
*/
|
||||
public function getTypeAttribute()
|
||||
{
|
||||
return $this->order_item->type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ class CartController extends Controller
|
|||
* Function to move a already added product to wishlist will run only on customer authentication.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return mixed
|
||||
*/
|
||||
public function moveToWishlist($id)
|
||||
{
|
||||
|
|
@ -153,7 +153,9 @@ class CartController extends Controller
|
|||
session()->flash('warning', trans('shop::app.checkout.cart.move-to-wishlist-error'));
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
return request()->get('redirect') !== false
|
||||
? redirect()->back()
|
||||
: response()->json([]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function
|
|||
])->name('shop.checkout.success');
|
||||
|
||||
//Shop buynow button action
|
||||
Route::get('move/wishlist/{id}', 'Webkul\Shop\Http\Controllers\CartController@moveToWishlist')->name('shop.movetowishlist');
|
||||
Route::post('move/wishlist/{id}', 'Webkul\Shop\Http\Controllers\CartController@moveToWishlist')->name('shop.movetowishlist');
|
||||
|
||||
Route::get('/downloadable/download-sample/{type}/{id}', 'Webkul\Shop\Http\Controllers\ProductController@downloadSample')->name('shop.downloadable.download_sample');
|
||||
|
||||
|
|
@ -176,13 +176,13 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function
|
|||
])->name('customer.session.destroy');
|
||||
|
||||
//Customer Wishlist add
|
||||
Route::get('wishlist/add/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@add')->name('customer.wishlist.add');
|
||||
Route::post('wishlist/add/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@add')->name('customer.wishlist.add');
|
||||
|
||||
//Customer Wishlist remove
|
||||
Route::get('wishlist/remove/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@remove')->name('customer.wishlist.remove');
|
||||
Route::delete('wishlist/remove/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@remove')->name('customer.wishlist.remove');
|
||||
|
||||
//Customer Wishlist remove
|
||||
Route::get('wishlist/removeall', 'Webkul\Customer\Http\Controllers\WishlistController@removeAll')->name('customer.wishlist.removeall');
|
||||
Route::delete('wishlist/removeall', 'Webkul\Customer\Http\Controllers\WishlistController@removeAll')->name('customer.wishlist.removeall');
|
||||
|
||||
//Customer Wishlist move to cart
|
||||
Route::get('wishlist/move/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@move')->name('customer.wishlist.move');
|
||||
|
|
|
|||
|
|
@ -93,9 +93,17 @@
|
|||
@if ($showWishlist)
|
||||
<span class="towishlist">
|
||||
@if ($item->parent_id != 'null' ||$item->parent_id != null)
|
||||
<a href="{{ route('shop.movetowishlist', $item->id) }}" onclick="removeLink('{{ __('shop::app.checkout.cart.cart-remove-action') }}')">{{ __('shop::app.checkout.cart.move-to-wishlist') }}</a>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
onclick="moveToWishlist('{{ __('shop::app.checkout.cart.cart-remove-action') }}', '{{ route('shop.movetowishlist', $item->id) }}')">
|
||||
{{ __('shop::app.checkout.cart.move-to-wishlist') }}
|
||||
</a>
|
||||
@else
|
||||
<a href="{{ route('shop.movetowishlist', $item->child->id) }}" onclick="removeLink('{{ __('shop::app.checkout.cart.cart-remove-action') }}')">{{ __('shop::app.checkout.cart.move-to-wishlist') }}</a>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
onclick="moveToWishlist('{{ __('shop::app.checkout.cart.cart-remove-action') }}', '{{ route('shop.movetowishlist', $item->child->id) }}')">
|
||||
{{ __('shop::app.checkout.cart.move-to-wishlist') }}
|
||||
</a>
|
||||
@endif
|
||||
</span>
|
||||
@endif
|
||||
|
|
@ -249,8 +257,22 @@
|
|||
});
|
||||
|
||||
function removeLink(message) {
|
||||
if (!confirm(message))
|
||||
event.preventDefault();
|
||||
if (! confirm(message)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function moveToWishlist(message, route) {
|
||||
if (! confirm(message)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
axios.post(route, {'redirect': false})
|
||||
.then((response) => {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function updateCartQunatity(operation, index) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,17 @@
|
|||
|
||||
@if (count($items))
|
||||
<div class="account-action">
|
||||
<a href="{{ route('customer.wishlist.removeall') }}">{{ __('shop::app.customer.account.wishlist.deleteall') }}</a>
|
||||
<form id="remove-all-wishlist" action="{{ route('customer.wishlist.removeall') }}" method="POST">
|
||||
@method('DELETE')
|
||||
|
||||
@csrf
|
||||
</form>
|
||||
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
onclick="document.getElementById('remove-all-wishlist').submit();">
|
||||
{{ __('shop::app.customer.account.wishlist.deleteall') }}
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
|
@ -62,7 +72,16 @@
|
|||
</div>
|
||||
|
||||
<div class="operations">
|
||||
<a class="mb-50" href="{{ route('customer.wishlist.remove', $item->id) }}">
|
||||
<form id="wishlist-{{ $item->id }}" action="{{ route('customer.wishlist.remove', $item->id) }}" method="POST">
|
||||
@method('DELETE')
|
||||
|
||||
@csrf
|
||||
</form>
|
||||
|
||||
<a
|
||||
class="mb-50"
|
||||
href="javascript:void(0);"
|
||||
onclick="document.getElementById('wishlist-{{ $item->id }}').submit();">
|
||||
<span class="icon trash-icon"></span>
|
||||
</a>
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,15 @@
|
|||
|
||||
@case('addToCartHtml')
|
||||
<div class="action">
|
||||
<div v-html="product.addToCartHtml"></div>
|
||||
<form :action="`${baseUrl}/checkout/cart/add/${product.product_id}`" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="product_id" :value="product.product_id">
|
||||
|
||||
<input type="hidden" name="quantity" value="1">
|
||||
|
||||
<div v-html="product.addToCartHtml"></div>
|
||||
</form>
|
||||
|
||||
<span class="icon white-cross-sm-icon remove-product" @click="removeProductCompare(product.id)"></span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -64,7 +64,18 @@
|
|||
@endphp
|
||||
|
||||
@if ($showWishlist)
|
||||
<a @if ($wishListHelper->getWishlistProduct($product)) class="add-to-wishlist already" @else class="add-to-wishlist" @endif href="{{ route('customer.wishlist.add', $product->product_id) }}">
|
||||
<form id="wishlist-{{ $product->product_id }}" action="{{ route('customer.wishlist.add', $product->product_id) }}" method="POST">
|
||||
@csrf
|
||||
</form>
|
||||
|
||||
<a
|
||||
@if ($wishListHelper->getWishlistProduct($product))
|
||||
class="add-to-wishlist already"
|
||||
@else
|
||||
class="add-to-wishlist"
|
||||
@endif
|
||||
href="javascript:void(0);"
|
||||
onclick="document.getElementById('wishlist-{{ $product->product_id }}').submit();">
|
||||
</a>
|
||||
@endif
|
||||
@endauth
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
@auth('customer')
|
||||
{!! view_render_event('bagisto.shop.products.wishlist.before') !!}
|
||||
|
||||
<form id="wishlist-{{ $product->product_id }}" action="{{ route('customer.wishlist.add', $product->product_id) }}" method="POST">
|
||||
@csrf
|
||||
</form>
|
||||
|
||||
<a
|
||||
@if ($wishListHelper->getWishlistProduct($product))
|
||||
class="add-to-wishlist already"
|
||||
|
|
@ -13,8 +17,11 @@
|
|||
@endif
|
||||
id="wishlist-changer"
|
||||
style="margin-right: 15px;"
|
||||
href="{{ route('customer.wishlist.add', $product->product_id) }}">
|
||||
href="javascript:void(0);"
|
||||
onclick="document.getElementById('wishlist-{{ $product->product_id }}').submit();">
|
||||
|
||||
<span class="icon wishlist-icon"></span>
|
||||
|
||||
</a>
|
||||
|
||||
{!! view_render_event('bagisto.shop.products.wishlist.after') !!}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'admin' => [
|
||||
'system' => [
|
||||
'social-login' => 'سوشیال لاگین',
|
||||
'enable-facebook' => 'فعالسازی فیس بوک',
|
||||
'enable-twitter' => 'فعال سازی توییتر',
|
||||
'enable-google' => 'فعال سازی گوگل',
|
||||
'enable-linkedin' => 'فعال سازی لینکدین',
|
||||
'enable-github' => 'فعال سازی گیت هاب'
|
||||
]
|
||||
],
|
||||
|
||||
'shop' => [
|
||||
'customer' => [
|
||||
'login-form' => [
|
||||
'continue-with-facebook' => 'ادامه با فیس بوک',
|
||||
'continue-with-twitter' => 'ادامه با توییتر',
|
||||
'continue-with-google' => 'ادامه با گوگل',
|
||||
'continue-with-linkedin' => 'ادامه با لینکدین',
|
||||
'continue-with-github' => 'ادامه با گیت هاب',
|
||||
'or' => 'یا'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
@ -4,14 +4,14 @@ return [
|
|||
'admin' => [
|
||||
'system' => [
|
||||
'taxes' => [
|
||||
'taxes' => 'Taxes',
|
||||
'catalogue' => 'Catalog',
|
||||
'pricing' => 'Pricing',
|
||||
'tax-inclusive' => 'Tax inclusive',
|
||||
'default-location-calculation' => 'Default Location Calculation',
|
||||
'default-country' => 'Default Country',
|
||||
'default-state' => 'Default State',
|
||||
'default-post-code' => 'Default Post Code',
|
||||
'taxes' => 'مالیت',
|
||||
'catalogue' => 'کاتالوگ',
|
||||
'pricing' => 'قیمت گذاری',
|
||||
'tax-inclusive' => 'شامل مالیت',
|
||||
'default-location-calculation' => 'مکان محاسبه پیشفرض',
|
||||
'default-country' => 'کشور پیشفرض',
|
||||
'default-state' => 'استان پیشفرض',
|
||||
'default-post-code' => 'کد پستی پیشفرض',
|
||||
],
|
||||
]
|
||||
]
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"/js/ui.js": "/js/ui.js?id=4abc33791463568de076",
|
||||
"/js/ui.js": "/js/ui.js?id=5ad9ef8dc0f7e2a59c75",
|
||||
"/css/ui.css": "/css/ui.css?id=87c15a3e7af4ab272377"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1475,8 +1475,6 @@
|
|||
_method: element.getAttribute("data-method")
|
||||
})
|
||||
.then(function(response) {
|
||||
this.result = response;
|
||||
|
||||
if (response.data.redirect) {
|
||||
window.location.href = response.data.redirect;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@
|
|||
"bootstrap-sass": "^3.4.1",
|
||||
"font-awesome": "^4.7.0",
|
||||
"lazysizes": "^5.2.2",
|
||||
"material-icons": "^0.3.1",
|
||||
"material-icons": "^0.7.6",
|
||||
"vee-validate": "^2.2.15",
|
||||
"vue-slider-component": "^3.1.0",
|
||||
"vue-toast-notification": "0.0.2"
|
||||
"vue-slider-component": "^3.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"/js/velocity.js": "/js/velocity.js?id=1c12a991b9a3d04715bd",
|
||||
"/js/velocity.js": "/js/velocity.js?id=5b0e7e5d2810ad90cde3",
|
||||
"/css/velocity-admin.css": "/css/velocity-admin.css?id=4322502d80a0e4a0affd",
|
||||
"/css/velocity.css": "/css/velocity.css?id=e17eb072b66c4c8c1227"
|
||||
"/css/velocity.css": "/css/velocity.css?id=b3d53fa8c0b5a7da14b6",
|
||||
"/js/velocity-core.js": "/js/velocity-core.js?id=5c0fe2bf195ee94576fd"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
namespace Webkul\Velocity\Helpers;
|
||||
|
||||
use Webkul\Product\Helpers\Review;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Webkul\Product\Facades\ProductImage;
|
||||
use Webkul\Product\Models\Product as ProductModel;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Product\Repositories\ProductFlatRepository;
|
||||
use Webkul\Velocity\Repositories\OrderBrandsRepository;
|
||||
use Webkul\Product\Repositories\ProductReviewRepository;
|
||||
use Webkul\Attribute\Repositories\AttributeOptionRepository;
|
||||
use Webkul\Product\Facades\ProductImage;
|
||||
use Webkul\Product\Helpers\Review;
|
||||
use Webkul\Product\Models\Product as ProductModel;
|
||||
use Webkul\Product\Repositories\ProductFlatRepository;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Product\Repositories\ProductReviewRepository;
|
||||
use Webkul\Velocity\Repositories\OrderBrandsRepository;
|
||||
use Webkul\Velocity\Repositories\VelocityMetadataRepository;
|
||||
|
||||
class Helper extends Review
|
||||
|
|
@ -247,6 +247,36 @@ class Helper extends Review
|
|||
return $reviews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messages from session.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
$message = [
|
||||
'message' => '',
|
||||
'messageType' => '',
|
||||
'messageLabel' => '',
|
||||
];
|
||||
|
||||
if ($message['message'] = session('success')) {
|
||||
$message['messageType'] = 'alert-success';
|
||||
$message['messageLabel'] = __('velocity::app.shop.general.alert.success');
|
||||
} else if ($message['message'] = session('warning')) {
|
||||
$message['messageType'] = 'alert-warning';
|
||||
$message['messageLabel'] = __('velocity::app.shop.general.alert.warning');
|
||||
} else if ($message['message'] = session('error')) {
|
||||
$message['messageType'] = 'alert-danger';
|
||||
$message['messageLabel'] = __('velocity::app.shop.general.alert.error');
|
||||
} else if ($message['message'] = session('info')) {
|
||||
$message['messageType'] = 'alert-info';
|
||||
$message['messageLabel'] = __('velocity::app.shop.general.alert.info');
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get json translations.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
namespace Webkul\Velocity\Providers;
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Foundation\AliasLoader;
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Webkul\Velocity\Facades\Velocity as VelocityFacade;
|
||||
|
||||
|
|
@ -55,11 +56,13 @@ class VelocityServiceProvider extends ServiceProvider
|
|||
protected function registerConfig()
|
||||
{
|
||||
$this->mergeConfigFrom(
|
||||
dirname(__DIR__) . '/Config/admin-menu.php', 'menu.admin'
|
||||
dirname(__DIR__) . '/Config/admin-menu.php',
|
||||
'menu.admin'
|
||||
);
|
||||
|
||||
$this->mergeConfigFrom(
|
||||
dirname(__DIR__) . '/Config/acl.php', 'acl'
|
||||
dirname(__DIR__) . '/Config/acl.php',
|
||||
'acl'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +93,7 @@ class VelocityServiceProvider extends ServiceProvider
|
|||
__DIR__ . '/../Resources/views/shop' => resource_path('themes/velocity/views'),
|
||||
]);
|
||||
|
||||
$this->publishes([__DIR__.'/../Resources/lang' => resource_path('lang/vendor/velocity')]);
|
||||
$this->publishes([__DIR__ . '/../Resources/lang' => resource_path('lang/vendor/velocity')]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -103,11 +106,11 @@ class VelocityServiceProvider extends ServiceProvider
|
|||
private function loadGloableVariables()
|
||||
{
|
||||
view()->composer('*', function ($view) {
|
||||
$velocityHelper = app('Webkul\Velocity\Helpers\Helper');
|
||||
$velocityMetaData = $velocityHelper->getVelocityMetaData();
|
||||
$velocityHelper = app(\Webkul\Velocity\Helpers\Helper::class);
|
||||
|
||||
$view->with('showRecentlyViewed', true);
|
||||
$view->with('velocityMetaData', $velocityMetaData);
|
||||
$view->with('velocityHelper', $velocityHelper);
|
||||
$view->with('velocityMetaData', $velocityHelper->getVelocityMetaData());
|
||||
});
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<div :class="`slides-container ${direction}`">
|
||||
<carousel-component
|
||||
loop="true"
|
||||
timeout="5000"
|
||||
autoplay="true"
|
||||
slides-per-page="1"
|
||||
navigation-enabled="hide"
|
||||
paginationEnabled="hide"
|
||||
:locale-direction="direction"
|
||||
:slides-count="banners.length > 0 ? banners.length : 1"
|
||||
>
|
||||
<template v-if="banners.length > 0">
|
||||
<slide
|
||||
v-for="(banner, index) in banners"
|
||||
:key="index"
|
||||
:slot="`slide-${index}`"
|
||||
title=" "
|
||||
>
|
||||
<a
|
||||
:href="
|
||||
banner.slider_path != ''
|
||||
? banner.slider_path
|
||||
: 'javascript:void(0);'
|
||||
"
|
||||
>
|
||||
<img
|
||||
class="col-12 no-padding banner-icon"
|
||||
:src="`${$root.baseUrl}/storage/${banner.path}`"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="show-content"
|
||||
v-html="banner.content.replace('\r\n', '')"
|
||||
></div>
|
||||
</a>
|
||||
</slide>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<slide slot="slide-0">
|
||||
<img
|
||||
loading="lazy"
|
||||
class="col-12 no-padding banner-icon"
|
||||
:src="defaultBanner"
|
||||
alt=""
|
||||
/>
|
||||
</slide>
|
||||
</template>
|
||||
</carousel-component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['direction', 'defaultBanner', 'banners'],
|
||||
|
||||
mounted: function() {
|
||||
let banners = this.$el.querySelectorAll('img');
|
||||
banners.forEach(banner => {
|
||||
banner.style.display = 'block';
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<a class="compare-btn unset" :href="src">
|
||||
<i class="material-icons">compare_arrows</i>
|
||||
|
||||
<div class="badge-container" v-if="compareCount > 0">
|
||||
<span class="badge" v-text="compareCount"></span>
|
||||
</div>
|
||||
|
||||
<span v-text="__('customer.compare.text')" v-if="isText == 'true'"></span>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: ['isCustomer', 'isText', 'src'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
compareCount: 0
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$root.headerItemsCount': function() {
|
||||
this.updateHeaderItemsCount();
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
this.updateHeaderItemsCount();
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateHeaderItemsCount: function() {
|
||||
if (this.isCustomer !== 'true') {
|
||||
let comparedItems = this.getStorageValue('compared_product');
|
||||
|
||||
if (comparedItems) {
|
||||
this.compareCount = comparedItems.length;
|
||||
}
|
||||
} else {
|
||||
this.$http
|
||||
.get(`${this.$root.baseUrl}/items-count`)
|
||||
.then(response => {
|
||||
this.compareCount = response.data.compareProductsCount;
|
||||
})
|
||||
.catch(exception => {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,475 @@
|
|||
<template>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div v-if="hamburger" class="nav-container scrollable">
|
||||
<div class="wrapper" v-if="this.rootCategories">
|
||||
<div class="greeting drawer-section fw6">
|
||||
<i class="material-icons">perm_identity</i>
|
||||
<span>
|
||||
<slot name="greetings"></slot>
|
||||
|
||||
<i
|
||||
@click="closeDrawer()"
|
||||
class="material-icons float-right text-dark"
|
||||
>
|
||||
cancel
|
||||
</i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ul
|
||||
type="none"
|
||||
class="velocity-content"
|
||||
v-if="headerContent.length > 0"
|
||||
>
|
||||
<li
|
||||
:key="index"
|
||||
v-for="(content, index) in headerContent"
|
||||
>
|
||||
<a
|
||||
class="unset"
|
||||
v-text="content.title"
|
||||
:href="`${$root.baseUrl}/${content.page_link}`"
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul
|
||||
type="none"
|
||||
class="category-wrapper"
|
||||
v-if="rootCategoriesCollection.length > 0"
|
||||
>
|
||||
<li
|
||||
v-for="(category,
|
||||
index) in rootCategoriesCollection"
|
||||
>
|
||||
<a
|
||||
class="unset"
|
||||
:href="`${$root.baseUrl}/${category.slug}`"
|
||||
>
|
||||
<div class="category-logo">
|
||||
<img
|
||||
class="category-icon"
|
||||
v-if="category.category_icon_path"
|
||||
:src="
|
||||
`${$root.baseUrl}/storage/${category.category_icon_path}`
|
||||
"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span v-text="category.name"></span>
|
||||
</a>
|
||||
|
||||
<i
|
||||
class="rango-arrow-right"
|
||||
@click="toggleSubcategories(index, $event)"
|
||||
></i>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<slot name="customer-navigation"></slot>
|
||||
|
||||
<ul type="none" class="meta-wrapper">
|
||||
<li>
|
||||
<template v-if="locale">
|
||||
<div class="language-logo-wrapper">
|
||||
<img
|
||||
class="language-logo"
|
||||
:src="
|
||||
`${$root.baseUrl}/storage/${locale.locale_image}`
|
||||
"
|
||||
alt=""
|
||||
v-if="locale.locale_image"
|
||||
/>
|
||||
|
||||
<img
|
||||
class="language-logo"
|
||||
:src="
|
||||
`${$root.baseUrl}/themes/velocity/assets/images/flags/en.png`
|
||||
"
|
||||
alt=""
|
||||
v-else-if="locale.code == 'en'"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span v-text="locale.name"></span>
|
||||
</template>
|
||||
|
||||
<i
|
||||
class="rango-arrow-right"
|
||||
@click="toggleMetaInfo('languages')"
|
||||
>
|
||||
</i>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span v-text="currency.code"></span>
|
||||
|
||||
<i
|
||||
class="rango-arrow-right"
|
||||
@click="toggleMetaInfo('currencies')"
|
||||
>
|
||||
</i>
|
||||
</li>
|
||||
|
||||
<slot name="extra-navigation"></slot>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="wrapper" v-else-if="subCategory">
|
||||
<div class="drawer-section">
|
||||
<i
|
||||
class="rango-arrow-left fs24 text-down-4"
|
||||
@click="toggleSubcategories('root')"
|
||||
></i>
|
||||
|
||||
<h4 class="display-inbl" v-text="subCategory.name"></h4>
|
||||
|
||||
<i
|
||||
class="material-icons float-right text-dark"
|
||||
@click="closeDrawer()"
|
||||
>
|
||||
cancel
|
||||
</i>
|
||||
</div>
|
||||
|
||||
<ul type="none">
|
||||
<li
|
||||
:key="index"
|
||||
v-for="(nestedSubCategory,
|
||||
index) in subCategory.children"
|
||||
>
|
||||
<a
|
||||
class="unset"
|
||||
:href="
|
||||
`${$root.baseUrl}/${subCategory.slug}/${nestedSubCategory.slug}`
|
||||
"
|
||||
>
|
||||
<div class="category-logo">
|
||||
<img
|
||||
class="category-icon"
|
||||
v-if="
|
||||
nestedSubCategory.category_icon_path
|
||||
"
|
||||
:src="
|
||||
`${$root.baseUrl}/storage/${nestedSubCategory.category_icon_path}`
|
||||
"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
/>
|
||||
</div>
|
||||
<span v-text="nestedSubCategory.name"></span>
|
||||
</a>
|
||||
|
||||
<ul
|
||||
type="none"
|
||||
class="nested-category"
|
||||
v-if="
|
||||
nestedSubCategory.children &&
|
||||
nestedSubCategory.children.length > 0
|
||||
"
|
||||
>
|
||||
<li
|
||||
:key="`index-${Math.random()}`"
|
||||
v-for="(thirdLevelCategory,
|
||||
index) in nestedSubCategory.children"
|
||||
>
|
||||
<a
|
||||
class="unset"
|
||||
:href="
|
||||
`${$root.baseUrl}/${subCategory.slug}/${nestedSubCategory.slug}/${thirdLevelCategory.slug}`
|
||||
"
|
||||
>
|
||||
<div class="category-logo">
|
||||
<img
|
||||
class="category-icon"
|
||||
v-if="
|
||||
thirdLevelCategory.category_icon_path
|
||||
"
|
||||
:src="
|
||||
`${$root.baseUrl}/storage/${thirdLevelCategory.category_icon_path}`
|
||||
"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span
|
||||
v-text="thirdLevelCategory.name"
|
||||
></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="wrapper" v-else-if="languages">
|
||||
<div class="drawer-section">
|
||||
<i
|
||||
class="rango-arrow-left fs24 text-down-4"
|
||||
@click="toggleMetaInfo('languages')"
|
||||
></i>
|
||||
<h4
|
||||
class="display-inbl"
|
||||
v-text="__('responsive.header.languages')"
|
||||
></h4>
|
||||
<i
|
||||
class="material-icons float-right text-dark"
|
||||
@click="closeDrawer()"
|
||||
>cancel</i
|
||||
>
|
||||
</div>
|
||||
|
||||
<ul type="none">
|
||||
<li v-for="(locale, index) in allLocales" :key="index">
|
||||
<a class="unset" :href="`?locale=${locale.code}`">
|
||||
<div class="category-logo">
|
||||
<img
|
||||
class="category-icon"
|
||||
:src="
|
||||
`${$root.baseUrl}/themes/velocity/assets/images/flags/en.png`
|
||||
"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
v-if="locale.code == 'en'"
|
||||
/>
|
||||
|
||||
<img
|
||||
class="category-icon"
|
||||
:src="
|
||||
`${$root.baseUrl}/storage/${locale.locale_image}`
|
||||
"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
v-else
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span v-text="locale.name"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="wrapper" v-else-if="currencies">
|
||||
<div class="drawer-section">
|
||||
<i
|
||||
class="rango-arrow-left fs24 text-down-4"
|
||||
@click="toggleMetaInfo('currencies')"
|
||||
></i>
|
||||
<h4
|
||||
class="display-inbl"
|
||||
v-text="__('shop.general.currencies')"
|
||||
></h4>
|
||||
<i
|
||||
class="material-icons float-right text-dark"
|
||||
@click="closeDrawer()"
|
||||
>cancel</i
|
||||
>
|
||||
</div>
|
||||
|
||||
<ul type="none">
|
||||
<li
|
||||
v-for="(currency, index) in allCurrencies"
|
||||
:key="index"
|
||||
>
|
||||
<a
|
||||
class="unset"
|
||||
:href="`?currency=${currency.code}`"
|
||||
>
|
||||
<span v-text="currency.code"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hamburger-wrapper" @click="toggleHamburger">
|
||||
<i class="rango-toggle hamburger"></i>
|
||||
</div>
|
||||
|
||||
<slot name="logo"></slot>
|
||||
</div>
|
||||
|
||||
<div class="right-vc-header col-6">
|
||||
<slot name="top-header"></slot>
|
||||
|
||||
<a class="unset cursor-pointer" @click="openSearchBar">
|
||||
<i class="material-icons">search</i>
|
||||
</a>
|
||||
|
||||
<a :href="cartRoute" class="unset">
|
||||
<i class="material-icons text-down-3">shopping_cart</i>
|
||||
|
||||
<div class="badge-wrapper">
|
||||
<span class="badge" v-text="updatedCartItemsCount"></span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="right searchbar" v-if="isSearchbar">
|
||||
<slot name="search-bar"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: [
|
||||
'isCustomer',
|
||||
'heading',
|
||||
'headerContent',
|
||||
'categoryCount',
|
||||
'cartItemsCount',
|
||||
'cartRoute',
|
||||
'locale',
|
||||
'allLocales',
|
||||
'currency',
|
||||
'allCurrencies'
|
||||
],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
compareCount: 0,
|
||||
wishlistCount: 0,
|
||||
languages: false,
|
||||
hamburger: false,
|
||||
currencies: false,
|
||||
subCategory: null,
|
||||
isSearchbar: false,
|
||||
rootCategories: true,
|
||||
rootCategoriesCollection: this.$root.sharedRootCategories,
|
||||
updatedCartItemsCount: this.cartItemsCount
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
hamburger: function(value) {
|
||||
if (value) {
|
||||
document.body.classList.add('open-hamburger');
|
||||
} else {
|
||||
document.body.classList.remove('open-hamburger');
|
||||
}
|
||||
},
|
||||
|
||||
'$root.headerItemsCount': function() {
|
||||
this.updateHeaderItemsCount();
|
||||
},
|
||||
|
||||
'$root.miniCartKey': function() {
|
||||
this.getMiniCartDetails();
|
||||
},
|
||||
|
||||
'$root.sharedRootCategories': function(categories) {
|
||||
this.formatCategories(categories);
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
this.getMiniCartDetails();
|
||||
this.updateHeaderItemsCount();
|
||||
},
|
||||
|
||||
methods: {
|
||||
openSearchBar: function() {
|
||||
this.isSearchbar = !this.isSearchbar;
|
||||
|
||||
let footer = $('.footer');
|
||||
let homeContent = $('#home-right-bar-container');
|
||||
|
||||
if (this.isSearchbar) {
|
||||
footer[0].style.opacity = '.3';
|
||||
homeContent[0].style.opacity = '.3';
|
||||
} else {
|
||||
footer[0].style.opacity = '1';
|
||||
homeContent[0].style.opacity = '1';
|
||||
}
|
||||
},
|
||||
|
||||
toggleHamburger: function() {
|
||||
this.hamburger = !this.hamburger;
|
||||
},
|
||||
|
||||
closeDrawer: function() {
|
||||
$('.nav-container').hide();
|
||||
|
||||
this.toggleHamburger();
|
||||
this.rootCategories = true;
|
||||
},
|
||||
|
||||
toggleSubcategories: function(index, event) {
|
||||
if (index == 'root') {
|
||||
this.rootCategories = true;
|
||||
this.subCategory = false;
|
||||
} else {
|
||||
event.preventDefault();
|
||||
|
||||
let categories = this.$root.sharedRootCategories;
|
||||
this.rootCategories = false;
|
||||
this.subCategory = categories[index];
|
||||
}
|
||||
},
|
||||
|
||||
toggleMetaInfo: function(metaKey) {
|
||||
this.rootCategories = !this.rootCategories;
|
||||
|
||||
this[metaKey] = !this[metaKey];
|
||||
},
|
||||
|
||||
updateHeaderItemsCount: function() {
|
||||
if (this.isCustomer != 'true') {
|
||||
let comparedItems = this.getStorageValue('compared_product');
|
||||
|
||||
if (comparedItems) {
|
||||
this.compareCount = comparedItems.length;
|
||||
}
|
||||
} else {
|
||||
this.$http
|
||||
.get(`${this.$root.baseUrl}/items-count`)
|
||||
.then(response => {
|
||||
this.compareCount = response.data.compareProductsCount;
|
||||
this.wishlistCount =
|
||||
response.data.wishlistedProductsCount;
|
||||
})
|
||||
.catch(exception => {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getMiniCartDetails: function() {
|
||||
this.$http
|
||||
.get(`${this.$root.baseUrl}/mini-cart`)
|
||||
.then(response => {
|
||||
if (response.data.status) {
|
||||
this.updatedCartItemsCount =
|
||||
response.data.mini_cart.cart_items.length;
|
||||
}
|
||||
})
|
||||
.catch(exception => {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
});
|
||||
},
|
||||
|
||||
formatCategories: function(categories) {
|
||||
let slicedCategories = categories;
|
||||
let categoryCount = this.categoryCount ? this.categoryCount : 9;
|
||||
|
||||
if (slicedCategories && slicedCategories.length > categoryCount) {
|
||||
slicedCategories = categories.slice(0, categoryCount);
|
||||
}
|
||||
|
||||
this.rootCategoriesCollection = slicedCategories;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<ul type="none" class="no-margin">
|
||||
<li v-for="(content, index) in headerContent" :key="index">
|
||||
<a
|
||||
v-text="content.title"
|
||||
:href="`${$root.baseUrl}/${content['page_link']}`"
|
||||
v-if="
|
||||
content['content_type'] == 'link' ||
|
||||
content['content_type'] == 'category'
|
||||
"
|
||||
:target="content['link_target'] ? '_blank' : '_self'"
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['headerContent']
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<div class="btn-group full-width force-center">
|
||||
<div class="selectdiv">
|
||||
<select
|
||||
class="form-control fs13 styled-select"
|
||||
name="category"
|
||||
aria-label="Category"
|
||||
@change="focusInput($event)"
|
||||
>
|
||||
<option value="" v-text="__('header.all-categories')"></option>
|
||||
|
||||
<template
|
||||
v-for="(category, index) in $root.sharedRootCategories"
|
||||
>
|
||||
<option
|
||||
:key="index"
|
||||
selected="selected"
|
||||
:value="category.id"
|
||||
v-if="category.id == searchedQuery.category"
|
||||
v-text="category.name"
|
||||
>
|
||||
</option>
|
||||
|
||||
<option
|
||||
:key="index"
|
||||
:value="category.id"
|
||||
v-text="category.name"
|
||||
v-else
|
||||
></option>
|
||||
</template>
|
||||
</select>
|
||||
|
||||
<div class="select-icon-container d-inline-block float-right">
|
||||
<span class="select-icon rango-arrow-down"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
required
|
||||
name="term"
|
||||
type="search"
|
||||
class="form-control"
|
||||
:placeholder="__('header.search-text')"
|
||||
aria-label="Search"
|
||||
v-model:value="inputVal"
|
||||
/>
|
||||
|
||||
<slot name="image-search"></slot>
|
||||
|
||||
<button
|
||||
class="btn"
|
||||
type="button"
|
||||
id="header-search-icon"
|
||||
aria-label="Search"
|
||||
@click="submitForm"
|
||||
>
|
||||
<i class="fs16 fw6 rango-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
data: function() {
|
||||
return {
|
||||
inputVal: '',
|
||||
searchedQuery: []
|
||||
};
|
||||
},
|
||||
|
||||
created: function() {
|
||||
let searchedItem = window.location.search.replace('?', '');
|
||||
searchedItem = searchedItem.split('&');
|
||||
|
||||
let updatedSearchedCollection = {};
|
||||
|
||||
searchedItem.forEach(item => {
|
||||
let splitedItem = item.split('=');
|
||||
updatedSearchedCollection[splitedItem[0]] = decodeURI(
|
||||
splitedItem[1]
|
||||
);
|
||||
});
|
||||
|
||||
if (updatedSearchedCollection['image-search'] == 1) {
|
||||
updatedSearchedCollection.term = '';
|
||||
}
|
||||
|
||||
this.searchedQuery = updatedSearchedCollection;
|
||||
|
||||
if (this.searchedQuery.term) {
|
||||
this.inputVal = decodeURIComponent(
|
||||
this.searchedQuery.term.split('+').join(' ')
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
focusInput: function(event) {
|
||||
$(event.target.parentElement.parentElement)
|
||||
.find('input')
|
||||
.focus();
|
||||
},
|
||||
|
||||
submitForm: function() {
|
||||
if (this.inputVal !== '') {
|
||||
$('input[name=term]').val(this.inputVal);
|
||||
$('#search-form').submit();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div
|
||||
id="main-category"
|
||||
:class="
|
||||
`main-category fs16 unselectable fw6 ${
|
||||
$root.sharedRootCategories.length > 0
|
||||
? 'cursor-pointer'
|
||||
: 'cursor-not-allowed'
|
||||
} left`
|
||||
"
|
||||
@mouseout="toggleSidebar('0', $event, 'mouseout')"
|
||||
@mouseover="toggleSidebar('0', $event, 'mouseover')"
|
||||
>
|
||||
<i class="rango-view-list text-down-4 align-vertical-top fs18"> </i>
|
||||
|
||||
<span
|
||||
class="pl5"
|
||||
v-text="heading"
|
||||
@mouseover="toggleSidebar('0', $event, 'mouseover')"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['heading']
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<a class="wishlist-btn unset" :href="src">
|
||||
<i class="material-icons">favorite_border</i>
|
||||
|
||||
<div class="badge-container" v-if="wishlistCount > 0">
|
||||
<span class="badge" v-text="wishlistCount"></span>
|
||||
</div>
|
||||
|
||||
<span v-text="__('header.wishlist')" v-if="isText == 'true'"></span>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: ['isCustomer', 'isText', 'src'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
wishlistCount: 0
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$root.headerItemsCount': function() {
|
||||
this.updateHeaderItemsCount();
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
this.updateHeaderItemsCount();
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateHeaderItemsCount: function() {
|
||||
if (this.isCustomer == 'true') {
|
||||
this.$http
|
||||
.get(`${this.$root.baseUrl}/items-count`)
|
||||
.then(response => {
|
||||
this.wishlistCount =
|
||||
response.data.wishlistedProductsCount;
|
||||
})
|
||||
.catch(exception => {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div class="container-fluid hot-categories-container">
|
||||
<card-list-header :heading="heading"></card-list-header>
|
||||
|
||||
<div class="row">
|
||||
<hot-category
|
||||
v-for="(category, index) in categories"
|
||||
:key="index"
|
||||
:slug="category"
|
||||
></hot-category>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['heading', 'categories']
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<a
|
||||
:class="`left ${addClass}`"
|
||||
:href="redirectSrc"
|
||||
aria-label="Logo"
|
||||
>
|
||||
<img class="logo" :src="imgSrc" alt="" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
template: '#logo-template',
|
||||
props: ['addClass', 'imgSrc', 'redirectSrc']
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
<template>
|
||||
<div class="d-inline-block image-search-container" v-if="status == 'true'">
|
||||
<label for="image-search-container">
|
||||
<i class="icon camera-icon"></i>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
class="d-none"
|
||||
ref="image_search_input"
|
||||
id="image-search-container"
|
||||
v-on:change="loadLibrary()"
|
||||
/>
|
||||
|
||||
<img
|
||||
class="d-none"
|
||||
id="uploaded-image-url"
|
||||
:src="uploadedImageUrl"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['status', 'uploadSrc', 'viewSrc', 'commonError', 'sizeLimitEror'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
uploadedImageUrl: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* This method will dynamically load the scripts. Because image search library
|
||||
* only used when someone clicks or interact with the image button. This will
|
||||
* reduce some data usage for mobile user.
|
||||
*/
|
||||
loadLibrary: function() {
|
||||
this.loadDynamicScript(
|
||||
'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs',
|
||||
() => {
|
||||
this.loadDynamicScript(
|
||||
'https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet',
|
||||
() => {
|
||||
this.uploadImage();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method will analyze the image and load the sets on the bases of trained model.
|
||||
*/
|
||||
uploadImage: function() {
|
||||
var imageInput = this.$refs.image_search_input;
|
||||
|
||||
if (imageInput.files && imageInput.files[0]) {
|
||||
if (imageInput.files[0].type.includes('image/')) {
|
||||
if (imageInput.files[0].size <= 2000000) {
|
||||
this.$root.showLoader();
|
||||
|
||||
var formData = new FormData();
|
||||
|
||||
formData.append('image', imageInput.files[0]);
|
||||
|
||||
axios
|
||||
.post(this.uploadSrc, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
var net;
|
||||
var self = this;
|
||||
this.uploadedImageUrl = response.data;
|
||||
|
||||
async function app() {
|
||||
var analysedResult = [];
|
||||
|
||||
var queryString = '';
|
||||
|
||||
net = await mobilenet.load();
|
||||
|
||||
const imgElement = document.getElementById(
|
||||
'uploaded-image-url'
|
||||
);
|
||||
|
||||
try {
|
||||
const result = await net.classify(
|
||||
imgElement
|
||||
);
|
||||
|
||||
result.forEach(function(value) {
|
||||
queryString = value.className.split(
|
||||
','
|
||||
);
|
||||
|
||||
if (queryString.length > 1) {
|
||||
analysedResult = analysedResult.concat(
|
||||
queryString
|
||||
);
|
||||
} else {
|
||||
analysedResult.push(
|
||||
queryString[0]
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
self.$root.hideLoader();
|
||||
|
||||
window.showAlert(
|
||||
`alert-danger`,
|
||||
this.__('shop.general.alert.error'),
|
||||
this.commonError
|
||||
);
|
||||
}
|
||||
|
||||
localStorage.searchedImageUrl =
|
||||
self.uploadedImageUrl;
|
||||
|
||||
queryString = localStorage.searched_terms = analysedResult.join(
|
||||
'_'
|
||||
);
|
||||
|
||||
self.$root.hideLoader();
|
||||
|
||||
window.location.href = `${self.viewSrc}?term=${queryString}&image-search=1`;
|
||||
}
|
||||
|
||||
app();
|
||||
})
|
||||
.catch(() => {
|
||||
this.$root.hideLoader();
|
||||
|
||||
window.showAlert(
|
||||
`alert-danger`,
|
||||
this.__('shop.general.alert.error'),
|
||||
this.commonError
|
||||
);
|
||||
});
|
||||
} else {
|
||||
imageInput.value = '';
|
||||
|
||||
window.showAlert(
|
||||
`alert-danger`,
|
||||
this.__('shop.general.alert.error'),
|
||||
this.sizeLimitEror
|
||||
);
|
||||
}
|
||||
} else {
|
||||
imageInput.value = '';
|
||||
|
||||
alert('Only images (.jpeg, .jpg, .png, ..) are allowed.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<button
|
||||
type="button"
|
||||
id="mini-cart"
|
||||
@click="toggleMiniCart"
|
||||
:class="
|
||||
`btn btn-link disable-box-shadow ${
|
||||
itemCount == 0 ? 'cursor-not-allowed' : ''
|
||||
}`
|
||||
"
|
||||
>
|
||||
<div class="mini-cart-content">
|
||||
<i class="material-icons-outlined text-down-3">shopping_cart</i>
|
||||
<span class="badge" v-text="itemCount" v-if="itemCount != 0"></span>
|
||||
<span class="fs18 fw6 cart-text" v-text="cartText"></span>
|
||||
</div>
|
||||
|
||||
<div class="down-arrow-container">
|
||||
<span class="rango-arrow-down"></span>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['itemCount', 'cartText'],
|
||||
|
||||
methods: {
|
||||
toggleMiniCart: function() {
|
||||
let modal = $('#cart-modal-content')[0];
|
||||
|
||||
if (modal) modal.classList.toggle('hide');
|
||||
|
||||
let accountModal = $('.account-modal')[0];
|
||||
|
||||
if (accountModal) accountModal.classList.add('hide');
|
||||
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,37 +1,63 @@
|
|||
<template>
|
||||
<div :class="`dropdown ${cartItems.length > 0 ? '' : 'disable-active'}`">
|
||||
<cart-btn :item-count="cartItems.length"></cart-btn>
|
||||
<mini-cart-button
|
||||
:item-count="cartItems.length"
|
||||
:cart-text="cartText"
|
||||
></mini-cart-button>
|
||||
|
||||
<div
|
||||
id="cart-modal-content"
|
||||
v-if="cartItems.length > 0"
|
||||
class="modal-content sensitive-modal cart-modal-content hide">
|
||||
|
||||
class="modal-content sensitive-modal cart-modal-content hide"
|
||||
>
|
||||
<div class="mini-cart-container">
|
||||
<div class="row small-card-container" :key="index" v-for="(item, index) in cartItems">
|
||||
<div
|
||||
class="row small-card-container"
|
||||
:key="index"
|
||||
v-for="(item, index) in cartItems"
|
||||
>
|
||||
<div class="col-3 product-image-container mr15">
|
||||
<a @click="removeProduct(item.id)">
|
||||
<span class="rango-close"></span>
|
||||
</a>
|
||||
|
||||
<a class="unset" :href="`${$root.baseUrl}/${item.url_key}`">
|
||||
<a
|
||||
class="unset"
|
||||
:href="`${$root.baseUrl}/${item.url_key}`"
|
||||
>
|
||||
<div
|
||||
class="product-image"
|
||||
:style="`background-image: url(${item.images.medium_image_url});`">
|
||||
</div>
|
||||
:style="
|
||||
`background-image: url(${item.images.medium_image_url});`
|
||||
"
|
||||
></div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-9 no-padding card-body align-vertical-top">
|
||||
<div class="no-padding">
|
||||
<div class="fs16 text-nowrap fw6" v-html="item.name"></div>
|
||||
<div
|
||||
class="fs16 text-nowrap fw6"
|
||||
v-html="item.name"
|
||||
></div>
|
||||
|
||||
<div class="fs18 card-current-price fw6">
|
||||
<div class="display-inbl">
|
||||
<label class="fw5">{{ __('checkout.qty') }}</label>
|
||||
<input type="text" disabled :value="item.quantity" class="ml5" />
|
||||
<label class="fw5">{{
|
||||
__('checkout.qty')
|
||||
}}</label>
|
||||
<input
|
||||
type="text"
|
||||
disabled
|
||||
:value="item.quantity"
|
||||
class="ml5"
|
||||
/>
|
||||
</div>
|
||||
<span class="card-total-price fw6">
|
||||
{{ isTaxInclusive == '1' ? item.base_total_with_tax : item.base_total }}
|
||||
{{
|
||||
isTaxInclusive == '1'
|
||||
? item.base_total_with_tax
|
||||
: item.base_total
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -44,17 +70,25 @@
|
|||
{{ subtotalText }}
|
||||
</h5>
|
||||
|
||||
<h5 class="col-6 text-right fw6 no-padding">{{ isTaxInclusive == '1' ? cartInformation.base_grand_total : cartInformation.base_sub_total }}</h5>
|
||||
<h5 class="col-6 text-right fw6 no-padding">
|
||||
{{
|
||||
isTaxInclusive == '1'
|
||||
? cartInformation.base_grand_total
|
||||
: cartInformation.base_sub_total
|
||||
}}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<a class="col text-left fs16 link-color remove-decoration" :href="viewCart">{{ cartText }}</a>
|
||||
<a
|
||||
class="col text-left fs16 link-color remove-decoration"
|
||||
:href="viewCartRoute"
|
||||
>{{ viewCartText }}</a
|
||||
>
|
||||
|
||||
<div class="col text-right no-padding">
|
||||
<a :href="checkoutUrl" @click="checkMinimumOrder($event)">
|
||||
<button
|
||||
type="button"
|
||||
class="theme-btn fs16 fw6">
|
||||
<a :href="checkoutRoute" @click="checkMinimumOrder($event)">
|
||||
<button type="button" class="theme-btn fs16 fw6">
|
||||
{{ checkoutText }}
|
||||
</button>
|
||||
</a>
|
||||
|
|
@ -65,79 +99,88 @@
|
|||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
'isTaxInclusive',
|
||||
'cartText',
|
||||
'viewCart',
|
||||
'checkoutUrl',
|
||||
'checkoutText',
|
||||
'subtotalText',
|
||||
'checkMinimumOrderUrl'
|
||||
],
|
||||
export default {
|
||||
props: [
|
||||
'isTaxInclusive',
|
||||
'viewCartRoute',
|
||||
'checkoutRoute',
|
||||
'checkMinimumOrderRoute',
|
||||
'cartText',
|
||||
'viewCartText',
|
||||
'checkoutText',
|
||||
'subtotalText'
|
||||
],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
cartItems: [],
|
||||
cartInformation: [],
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
cartItems: [],
|
||||
cartInformation: []
|
||||
};
|
||||
},
|
||||
|
||||
mounted: function () {
|
||||
mounted: function() {
|
||||
this.getMiniCartDetails();
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$root.miniCartKey': function() {
|
||||
this.getMiniCartDetails();
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$root.miniCartKey': function () {
|
||||
this.getMiniCartDetails();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getMiniCartDetails: function () {
|
||||
this.$http.get(`${this.$root.baseUrl}/mini-cart`)
|
||||
methods: {
|
||||
getMiniCartDetails: function() {
|
||||
this.$http
|
||||
.get(`${this.$root.baseUrl}/mini-cart`)
|
||||
.then(response => {
|
||||
if (response.data.status) {
|
||||
this.cartItems = response.data.mini_cart.cart_items;
|
||||
this.cartInformation = response.data.mini_cart.cart_details;
|
||||
this.cartInformation =
|
||||
response.data.mini_cart.cart_details;
|
||||
}
|
||||
})
|
||||
.catch(exception => {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
removeProduct: function (productId) {
|
||||
this.$http.delete(`${this.$root.baseUrl}/cart/remove/${productId}`)
|
||||
removeProduct: function(productId) {
|
||||
this.$http
|
||||
.delete(`${this.$root.baseUrl}/cart/remove/${productId}`)
|
||||
.then(response => {
|
||||
this.cartItems = this.cartItems.filter(item => item.id != productId);
|
||||
this.cartItems = this.cartItems.filter(
|
||||
item => item.id != productId
|
||||
);
|
||||
this.$root.miniCartKey++;
|
||||
|
||||
window.showAlert(`alert-${response.data.status}`, response.data.label, response.data.message);
|
||||
window.showAlert(
|
||||
`alert-${response.data.status}`,
|
||||
response.data.label,
|
||||
response.data.message
|
||||
);
|
||||
})
|
||||
.catch(exception => {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
checkMinimumOrder: function (e) {
|
||||
e.preventDefault();
|
||||
checkMinimumOrder: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.$http.post(this.checkMinimumOrderUrl)
|
||||
.then(({ data }) => {
|
||||
if (! data.status) {
|
||||
window.showAlert(`alert-warning`, 'Warning', data.message);
|
||||
} else {
|
||||
window.location.href = this.checkoutUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.$http.post(this.checkMinimumOrderRoute).then(({ data }) => {
|
||||
if (!data.status) {
|
||||
window.showAlert(`alert-warning`, 'Warning', data.message);
|
||||
} else {
|
||||
window.location.href = this.checkoutRoute;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div class="modal-parent" v-if="$root.loading">
|
||||
<div class="overlay-loader">
|
||||
<div class="cp-spinner cp-round"></div>
|
||||
<div class="message-block" v-text="__('shop.overlay-loader.message')"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.message-block {
|
||||
position: relative;
|
||||
top: 60px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div class="container-fluid popular-categories-container">
|
||||
<card-list-header :heading="heading"></card-list-header>
|
||||
|
||||
<div class="row">
|
||||
<popular-category
|
||||
v-for="(category, index) in categories"
|
||||
:key="index"
|
||||
:slug="category"
|
||||
></popular-category>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['heading', 'categories']
|
||||
};
|
||||
</script>
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
:title="product.name"
|
||||
:href="`${baseUrl}/${product.slug}`">
|
||||
|
||||
<span class="fs16">{{ product.name | truncate }}</span>
|
||||
<span class="fs16">{{ product.name }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
props: {
|
||||
count: {
|
||||
type: String,
|
||||
default: 10
|
||||
default: '10'
|
||||
},
|
||||
productId: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div
|
||||
:class="
|
||||
`quantity control-group ${
|
||||
errors.has(controlName) ? 'has-error' : ''
|
||||
}`
|
||||
"
|
||||
>
|
||||
<label
|
||||
class="required"
|
||||
for="quantity-changer"
|
||||
v-text="quantityText"
|
||||
></label>
|
||||
|
||||
<button type="button" class="decrease" @click="decreaseQty()">-</button>
|
||||
|
||||
<input
|
||||
:value="qty"
|
||||
class="control"
|
||||
:name="controlName"
|
||||
:v-validate="validations"
|
||||
id="quantity-changer"
|
||||
:data-vv-as="`"${quantityText}"`"
|
||||
readonly
|
||||
/>
|
||||
|
||||
<button type="button" class="increase" @click="increaseQty()">+</button>
|
||||
|
||||
<span class="control-error" v-if="errors.has(controlName)">{{
|
||||
errors.first(controlName)
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
template: '#quantity-changer-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
props: {
|
||||
controlName: {
|
||||
type: String,
|
||||
default: 'quantity'
|
||||
},
|
||||
|
||||
quantity: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
},
|
||||
|
||||
quantityText: {
|
||||
type: String,
|
||||
default: 'Quantity'
|
||||
},
|
||||
|
||||
minQuantity: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
},
|
||||
|
||||
validations: {
|
||||
type: String,
|
||||
default: 'required|numeric|min_value:1'
|
||||
}
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
qty: this.quantity
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
quantity: function(val) {
|
||||
this.qty = val;
|
||||
|
||||
this.$emit('onQtyUpdated', this.qty);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
decreaseQty: function() {
|
||||
if (this.qty > this.minQuantity) this.qty = parseInt(this.qty) - 1;
|
||||
|
||||
this.$emit('onQtyUpdated', this.qty);
|
||||
},
|
||||
|
||||
increaseQty: function() {
|
||||
this.qty = parseInt(this.qty) + 1;
|
||||
|
||||
this.$emit('onQtyUpdated', this.qty);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* Main imports.
|
||||
*/
|
||||
import Vue from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* Helper functions.
|
||||
*/
|
||||
import {
|
||||
getBaseUrl,
|
||||
isMobile,
|
||||
loadDynamicScript,
|
||||
showAlert,
|
||||
removeTrailingSlash
|
||||
} from './app-helpers';
|
||||
|
||||
/**
|
||||
* Vue prototype.
|
||||
*/
|
||||
Vue.prototype.$http = axios;
|
||||
|
||||
/**
|
||||
* Window assignation.
|
||||
*/
|
||||
window.Vue = Vue;
|
||||
|
||||
window.eventBus = new Vue();
|
||||
|
||||
window.axios = axios;
|
||||
|
||||
window.jQuery = window.$ = require('jquery');
|
||||
|
||||
window.BootstrapSass = require('bootstrap-sass');
|
||||
|
||||
window.getBaseUrl = getBaseUrl;
|
||||
|
||||
window.isMobile = isMobile;
|
||||
|
||||
window.loadDynamicScript = loadDynamicScript;
|
||||
|
||||
window.showAlert = showAlert;
|
||||
|
||||
/**
|
||||
* Dynamic loading for mobile.
|
||||
*/
|
||||
$(function() {
|
||||
/**
|
||||
* Base url.
|
||||
*/
|
||||
let baseUrl = getBaseUrl();
|
||||
|
||||
/**
|
||||
* Velocity JS path. Just make sure if you are renaming
|
||||
* file then update this path also for mobile.
|
||||
*/
|
||||
let velocityJSPath = 'themes/velocity/assets/js/velocity.js';
|
||||
|
||||
if (
|
||||
isMobile() &&
|
||||
removeTrailingSlash(baseUrl) ===
|
||||
removeTrailingSlash(window.location.href)
|
||||
) {
|
||||
/**
|
||||
* Event for mobile to check the user interaction for the homepage. In mobile,
|
||||
* if your viewport is having dynamic content then, feel free to override this.
|
||||
* Else it is recommended to have some, static content in the viewport as the
|
||||
* first impression to reduce LCP.
|
||||
*/
|
||||
document.addEventListener(
|
||||
'touchstart',
|
||||
function dynamicScript() {
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
loadDynamicScript(`${baseUrl}/${velocityJSPath}`, () => {
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
document.body.style.overflow = '';
|
||||
|
||||
this.removeEventListener('touchstart', dynamicScript);
|
||||
});
|
||||
},
|
||||
false
|
||||
);
|
||||
} else {
|
||||
/**
|
||||
* Else leave it default as previous.
|
||||
*/
|
||||
loadDynamicScript(`${baseUrl}/${velocityJSPath}`, () => {});
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
export function getBaseUrl() {
|
||||
return document.querySelector('meta[name="base-url"]').content;
|
||||
}
|
||||
|
||||
export function isMobile() {
|
||||
if (
|
||||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i |
|
||||
/mobi/i.test(navigator.userAgent)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function loadDynamicScript(src, onScriptLoaded) {
|
||||
let dynamicScript = document.createElement('script');
|
||||
|
||||
dynamicScript.setAttribute('src', src);
|
||||
|
||||
document.body.appendChild(dynamicScript);
|
||||
|
||||
dynamicScript.addEventListener('load', onScriptLoaded, false);
|
||||
}
|
||||
|
||||
export function showAlert(messageType, messageLabel, message) {
|
||||
if (messageType && message !== '') {
|
||||
let alertId = Math.floor(Math.random() * 1000);
|
||||
|
||||
let html = `<div class="alert ${messageType} alert-dismissible" id="${alertId}">
|
||||
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
|
||||
<strong>${
|
||||
messageLabel ? messageLabel + '!' : ''
|
||||
} </strong> ${message}.
|
||||
</div>`;
|
||||
|
||||
$('#alert-container')
|
||||
.append(html)
|
||||
.ready(() => {
|
||||
window.setTimeout(() => {
|
||||
$(`#alert-container #${alertId}`).remove();
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function removeTrailingSlash(site) {
|
||||
return site.replace(/\/$/, '');
|
||||
}
|
||||
|
|
@ -1,140 +1,169 @@
|
|||
import Vue from 'vue';
|
||||
import accounting from 'accounting';
|
||||
/**
|
||||
* Main imports.
|
||||
*/
|
||||
import Accounting from 'accounting';
|
||||
import VeeValidate from 'vee-validate';
|
||||
import VueCarousel from 'vue-carousel';
|
||||
import VueToast from 'vue-toast-notification';
|
||||
import 'vue-toast-notification/dist/index.css';
|
||||
import de from 'vee-validate/dist/locale/de';
|
||||
import 'lazysizes';
|
||||
|
||||
/**
|
||||
* Lang imports.
|
||||
*/
|
||||
import ar from 'vee-validate/dist/locale/ar';
|
||||
import de from 'vee-validate/dist/locale/de';
|
||||
import fa from 'vee-validate/dist/locale/fa';
|
||||
import fr from 'vee-validate/dist/locale/fr';
|
||||
import nl from 'vee-validate/dist/locale/nl';
|
||||
import tr from 'vee-validate/dist/locale/tr';
|
||||
import VeeValidate, { Validator } from 'vee-validate';
|
||||
import axios from 'axios';
|
||||
import 'lazysizes';
|
||||
|
||||
window.axios = axios;
|
||||
window.VeeValidate = VeeValidate;
|
||||
window.jQuery = window.$ = require("jquery");
|
||||
window.BootstrapSass = require("bootstrap-sass");
|
||||
|
||||
Vue.use(VueToast);
|
||||
/**
|
||||
* Vue plugins.
|
||||
*/
|
||||
Vue.use(VueCarousel);
|
||||
Vue.use(BootstrapSass);
|
||||
Vue.prototype.$http = axios;
|
||||
|
||||
Vue.use(VeeValidate, {
|
||||
dictionary: {
|
||||
ar: ar,
|
||||
de: de,
|
||||
fa: fa,
|
||||
fr: fr,
|
||||
nl: nl,
|
||||
tr: tr,
|
||||
fa: fa,
|
||||
fr: fr,
|
||||
nl: nl,
|
||||
tr: tr
|
||||
}
|
||||
});
|
||||
|
||||
Vue.filter('currency', function (value, argument) {
|
||||
return accounting.formatMoney(value, argument);
|
||||
})
|
||||
/**
|
||||
* Filters.
|
||||
*/
|
||||
Vue.filter('currency', function(value, argument) {
|
||||
return Accounting.formatMoney(value, argument);
|
||||
});
|
||||
|
||||
window.Vue = Vue;
|
||||
window.Carousel = VueCarousel;
|
||||
|
||||
// UI components
|
||||
Vue.component("vue-slider", require("vue-slider-component"));
|
||||
/**
|
||||
* Global components.
|
||||
**/
|
||||
Vue.component('vue-slider', require('vue-slider-component'));
|
||||
Vue.component('mini-cart-button', require('./UI/components/mini-cart-button'));
|
||||
Vue.component('mini-cart', require('./UI/components/mini-cart'));
|
||||
Vue.component('modal-component', require('./UI/components/modal'));
|
||||
Vue.component("add-to-cart", require("./UI/components/add-to-cart"));
|
||||
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('quantity-changer', require('./UI/components/quantity-changer'));
|
||||
Vue.component('proceed-to-checkout', require('./UI/components/proceed-to-checkout'));
|
||||
Vue.component('compare-component-with-badge', require('./UI/components/header-compare-with-badge'));
|
||||
Vue.component('searchbar-component', require('./UI/components/header-searchbar'));
|
||||
Vue.component('wishlist-component-with-badge', require('./UI/components/header-wishlist-with-badge'));
|
||||
Vue.component('mobile-header', require('./UI/components/header-mobile'));
|
||||
Vue.component('sidebar-header', require('./UI/components/header-sidebar'));
|
||||
Vue.component('right-side-header', require('./UI/components/header-right-side'));
|
||||
Vue.component('sidebar-component', require('./UI/components/sidebar'));
|
||||
Vue.component("product-card", require("./UI/components/product-card"));
|
||||
Vue.component("wishlist-component", require("./UI/components/wishlist"));
|
||||
Vue.component('product-card', require('./UI/components/product-card'));
|
||||
Vue.component('wishlist-component', require('./UI/components/wishlist'));
|
||||
Vue.component('carousel-component', require('./UI/components/carousel'));
|
||||
Vue.component('slider-component', require('./UI/components/banners'));
|
||||
Vue.component('child-sidebar', require('./UI/components/child-sidebar'));
|
||||
Vue.component('card-list-header', require('./UI/components/card-header'));
|
||||
Vue.component('logo-component', require('./UI/components/image-logo'));
|
||||
Vue.component('magnify-image', require('./UI/components/image-magnifier'));
|
||||
Vue.component('image-search-component', require('./UI/components/image-search'));
|
||||
Vue.component('compare-component', require('./UI/components/product-compare'));
|
||||
Vue.component("shimmer-component", require("./UI/components/shimmer-component"));
|
||||
Vue.component('shimmer-component', require('./UI/components/shimmer-component'));
|
||||
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'));
|
||||
Vue.component('recently-viewed', require('./UI/components/recently-viewed'));
|
||||
Vue.component('product-collections', require('./UI/components/product-collections'));
|
||||
Vue.component('hot-category', require('./UI/components/hot-category'));
|
||||
Vue.component('hot-categories', require('./UI/components/hot-categories'));
|
||||
Vue.component('popular-category', require('./UI/components/popular-category'));
|
||||
Vue.component('popular-categories', require('./UI/components/popular-categories'));
|
||||
Vue.component('velocity-overlay-loader', require('./UI/components/overlay-loader'));
|
||||
Vue.component('vnode-injector', {
|
||||
functional: true,
|
||||
props: ['nodes'],
|
||||
render(h, { props }) {
|
||||
return props.nodes;
|
||||
}
|
||||
});
|
||||
|
||||
window.eventBus = new Vue();
|
||||
|
||||
$(document).ready(function () {
|
||||
// define a mixin object
|
||||
/**
|
||||
* Start from here.
|
||||
**/
|
||||
$(function() {
|
||||
/**
|
||||
* Define a mixin object.
|
||||
*/
|
||||
Vue.mixin(require('./UI/components/trans'));
|
||||
|
||||
Vue.mixin({
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
'imageObserver': null,
|
||||
'navContainer': false,
|
||||
'headerItemsCount': 0,
|
||||
'sharedRootCategories': [],
|
||||
'responsiveSidebarTemplate': '',
|
||||
'responsiveSidebarKey': Math.random(),
|
||||
'baseUrl': document.querySelector("script[src$='velocity.js']").getAttribute('baseUrl')
|
||||
}
|
||||
imageObserver: null,
|
||||
navContainer: false,
|
||||
headerItemsCount: 0,
|
||||
sharedRootCategories: [],
|
||||
responsiveSidebarTemplate: '',
|
||||
responsiveSidebarKey: Math.random(),
|
||||
baseUrl: getBaseUrl(),
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
redirect: function (route) {
|
||||
route ? window.location.href = route : '';
|
||||
redirect: function(route) {
|
||||
route ? (window.location.href = route) : '';
|
||||
},
|
||||
|
||||
debounceToggleSidebar: function (id, {target}, type) {
|
||||
// setTimeout(() => {
|
||||
this.toggleSidebar(id, target, type);
|
||||
// }, 500);
|
||||
debounceToggleSidebar: function(id, { target }, type) {
|
||||
this.toggleSidebar(id, target, type);
|
||||
},
|
||||
|
||||
toggleSidebar: function (id, {target}, type) {
|
||||
toggleSidebar: function(id, { target }, type) {
|
||||
if (
|
||||
Array.from(target.classList)[0] == "main-category"
|
||||
|| Array.from(target.parentElement.classList)[0] == "main-category"
|
||||
Array.from(target.classList)[0] == 'main-category' ||
|
||||
Array.from(target.parentElement.classList)[0] ==
|
||||
'main-category'
|
||||
) {
|
||||
let sidebar = $(`#sidebar-level-${id}`);
|
||||
if (sidebar && sidebar.length > 0) {
|
||||
if (type == "mouseover") {
|
||||
if (type == 'mouseover') {
|
||||
this.show(sidebar);
|
||||
} else if (type == "mouseout") {
|
||||
} else if (type == 'mouseout') {
|
||||
this.hide(sidebar);
|
||||
}
|
||||
}
|
||||
} 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-')) {
|
||||
let subCategories = $(`#${target.id ? target.id : parentItem.id} .sub-categories`);
|
||||
let subCategories = $(
|
||||
`#${
|
||||
target.id ? target.id : parentItem.id
|
||||
} .sub-categories`
|
||||
);
|
||||
|
||||
if (subCategories && subCategories.length > 0) {
|
||||
let subCategories1 = Array.from(subCategories)[0];
|
||||
subCategories1 = $(subCategories1);
|
||||
|
||||
if (type == "mouseover") {
|
||||
if (type == 'mouseover') {
|
||||
this.show(subCategories1);
|
||||
|
||||
let sidebarChild = subCategories1.find('.sidebar');
|
||||
let sidebarChild = subCategories1.find(
|
||||
'.sidebar'
|
||||
);
|
||||
this.show(sidebarChild);
|
||||
} else if (type == "mouseout") {
|
||||
} else if (type == 'mouseout') {
|
||||
this.hide(subCategories1);
|
||||
}
|
||||
} else {
|
||||
if (type == "mouseout") {
|
||||
if (type == 'mouseout') {
|
||||
let sidebar = $(`#${id}`);
|
||||
sidebar.hide();
|
||||
}
|
||||
|
|
@ -143,57 +172,53 @@ $(document).ready(function () {
|
|||
}
|
||||
},
|
||||
|
||||
show: function (element) {
|
||||
show: function(element) {
|
||||
element.show();
|
||||
element.mouseleave(({target}) => {
|
||||
element.mouseleave(({ target }) => {
|
||||
$(target.closest('.sidebar')).hide();
|
||||
});
|
||||
},
|
||||
|
||||
hide: function (element) {
|
||||
hide: function(element) {
|
||||
element.hide();
|
||||
},
|
||||
|
||||
toggleButtonDisability ({event, actionType}) {
|
||||
toggleButtonDisability({ event, actionType }) {
|
||||
let button = event.target.querySelector('button[type=submit]');
|
||||
|
||||
button ? button.disabled = actionType : '';
|
||||
button ? (button.disabled = actionType) : '';
|
||||
},
|
||||
|
||||
onSubmit: function (event) {
|
||||
this.toggleButtonDisability({event, actionType: true});
|
||||
onSubmit: function(event) {
|
||||
this.toggleButtonDisability({ event, actionType: true });
|
||||
|
||||
if(typeof tinyMCE !== 'undefined')
|
||||
tinyMCE.triggerSave();
|
||||
if (typeof tinyMCE !== 'undefined') tinyMCE.triggerSave();
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
event.target.submit();
|
||||
} else {
|
||||
this.toggleButtonDisability({event, actionType: false});
|
||||
this.toggleButtonDisability({
|
||||
event,
|
||||
actionType: false
|
||||
});
|
||||
|
||||
eventBus.$emit('onFormError')
|
||||
eventBus.$emit('onFormError');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
isMobile: function () {
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i|/mobi/i.test(navigator.userAgent)) {
|
||||
if (this.isMaxWidthCrossInLandScape()) {
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
isMobile: function() {
|
||||
return isMobile();
|
||||
},
|
||||
|
||||
isMaxWidthCrossInLandScape: function() {
|
||||
return window.innerWidth > 900;
|
||||
loadDynamicScript: function(src, onScriptLoaded) {
|
||||
loadDynamicScript(src, onScriptLoaded);
|
||||
},
|
||||
|
||||
getDynamicHTML: function (input) {
|
||||
var _staticRenderFns;
|
||||
getDynamicHTML: function(input) {
|
||||
let _staticRenderFns, output;
|
||||
|
||||
const { render, staticRenderFns } = Vue.compile(input);
|
||||
|
||||
if (this.$options.staticRenderFns.length > 0) {
|
||||
|
|
@ -203,7 +228,7 @@ $(document).ready(function () {
|
|||
}
|
||||
|
||||
try {
|
||||
var output = render.call(this, this.$createElement);
|
||||
output = render.call(this, this.$createElement);
|
||||
} catch (exception) {
|
||||
console.log(this.__('error.something_went_wrong'));
|
||||
}
|
||||
|
|
@ -213,7 +238,7 @@ $(document).ready(function () {
|
|||
return output;
|
||||
},
|
||||
|
||||
getStorageValue: function (key) {
|
||||
getStorageValue: function(key) {
|
||||
let value = window.localStorage.getItem(key);
|
||||
|
||||
if (value) {
|
||||
|
|
@ -223,92 +248,75 @@ $(document).ready(function () {
|
|||
return value;
|
||||
},
|
||||
|
||||
setStorageValue: function (key, value) {
|
||||
setStorageValue: function(key, value) {
|
||||
window.localStorage.setItem(key, JSON.stringify(value));
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const app = new Vue({
|
||||
el: "#app",
|
||||
VueToast,
|
||||
el: '#app',
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
loading: false,
|
||||
modalIds: {},
|
||||
miniCartKey: 0,
|
||||
quickView: false,
|
||||
productDetails: [],
|
||||
showPageLoader: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
created: function () {
|
||||
setTimeout(() => {
|
||||
document.body.classList.remove("modal-open");
|
||||
}, 0);
|
||||
|
||||
window.addEventListener('click', () => {
|
||||
let modals = document.getElementsByClassName('sensitive-modal');
|
||||
|
||||
Array.from(modals).forEach(modal => {
|
||||
modal.classList.add('hide');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
mounted: function () {
|
||||
setTimeout(() => {
|
||||
this.addServerErrors();
|
||||
}, 0);
|
||||
|
||||
document.body.style.display = "block";
|
||||
mounted: function() {
|
||||
this.$validator.localize(document.documentElement.lang);
|
||||
|
||||
this.addServerErrors();
|
||||
this.loadCategories();
|
||||
this.addIntersectionObserver();
|
||||
},
|
||||
|
||||
methods: {
|
||||
onSubmit: function (event) {
|
||||
this.toggleButtonDisability({event, actionType: true});
|
||||
onSubmit: function(event) {
|
||||
this.toggleButtonDisability({ event, actionType: true });
|
||||
|
||||
if(typeof tinyMCE !== 'undefined')
|
||||
tinyMCE.triggerSave();
|
||||
if (typeof tinyMCE !== 'undefined') tinyMCE.triggerSave();
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
event.target.submit();
|
||||
} else {
|
||||
this.toggleButtonDisability({event, actionType: false});
|
||||
this.toggleButtonDisability({
|
||||
event,
|
||||
actionType: false
|
||||
});
|
||||
|
||||
eventBus.$emit('onFormError')
|
||||
eventBus.$emit('onFormError');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggleButtonDisable (value) {
|
||||
var buttons = document.getElementsByTagName("button");
|
||||
toggleButtonDisable(value) {
|
||||
let buttons = document.getElementsByTagName('button');
|
||||
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
buttons[i].disabled = value;
|
||||
}
|
||||
},
|
||||
|
||||
addServerErrors: function (scope = null) {
|
||||
for (var key in serverErrors) {
|
||||
var inputNames = [];
|
||||
addServerErrors: function(scope = null) {
|
||||
for (let key in serverErrors) {
|
||||
let inputNames = [];
|
||||
key.split('.').forEach(function(chunk, index) {
|
||||
if(index) {
|
||||
inputNames.push('[' + chunk + ']')
|
||||
if (index) {
|
||||
inputNames.push('[' + chunk + ']');
|
||||
} else {
|
||||
inputNames.push(chunk)
|
||||
inputNames.push(chunk);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var inputName = inputNames.join('');
|
||||
let inputName = inputNames.join('');
|
||||
|
||||
const field = this.$validator.fields.find({
|
||||
name: inputName,
|
||||
|
|
@ -326,61 +334,62 @@ $(document).ready(function () {
|
|||
}
|
||||
},
|
||||
|
||||
addFlashMessages: function () {
|
||||
addFlashMessages: function() {
|
||||
if (window.flashMessages.alertMessage)
|
||||
window.alert(window.flashMessages.alertMessage);
|
||||
},
|
||||
|
||||
showModal: function (id) {
|
||||
showModal: function(id) {
|
||||
this.$set(this.modalIds, id, true);
|
||||
},
|
||||
|
||||
loadCategories: 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');
|
||||
})
|
||||
},
|
||||
|
||||
addIntersectionObserver: function () {
|
||||
this.imageObserver = new IntersectionObserver((entries, imgObserver) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
const lazyImage = entry.target
|
||||
lazyImage.src = lazyImage.dataset.src
|
||||
}
|
||||
loadCategories: 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');
|
||||
});
|
||||
},
|
||||
|
||||
showLoader: function () {
|
||||
$('#loader').show();
|
||||
$('.overlay-loader').show();
|
||||
|
||||
document.body.classList.add("modal-open");
|
||||
addIntersectionObserver: function() {
|
||||
this.imageObserver = new IntersectionObserver(
|
||||
(entries, imgObserver) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const lazyImage = entry.target;
|
||||
lazyImage.src = lazyImage.dataset.src;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
hideLoader: function () {
|
||||
$('#loader').hide();
|
||||
$('.overlay-loader').hide();
|
||||
showLoader: function() {
|
||||
this.loading = true;
|
||||
},
|
||||
|
||||
document.body.classList.remove("modal-open");
|
||||
}
|
||||
hideLoader: function() {
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
togglePopup: function() {
|
||||
let accountModal = $('#account-modal');
|
||||
|
||||
let modal = $('#cart-modal-content');
|
||||
|
||||
if (modal) modal.addClass('hide');
|
||||
|
||||
accountModal.toggleClass('hide');
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
window.app = app;
|
||||
|
||||
// for compilation of html coming from server
|
||||
Vue.component('vnode-injector', {
|
||||
functional: true,
|
||||
props: ['nodes'],
|
||||
render(h, {props}) {
|
||||
return props.nodes;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1746,9 +1746,15 @@
|
|||
min-height: 65vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main-container-wrapper {
|
||||
/**
|
||||
* Sticky header for logo and search component. Just make sure
|
||||
* this class should have height otherwise CLS score will reduce.
|
||||
*/
|
||||
.sticky-header {
|
||||
top: 0px;
|
||||
height: 55px;
|
||||
z-index: 100;
|
||||
position: sticky;
|
||||
background: white;
|
||||
|
|
@ -1759,7 +1765,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.search-container {
|
||||
padding: 30px 20px;
|
||||
|
||||
|
|
@ -2223,9 +2228,8 @@
|
|||
position: relative;
|
||||
|
||||
.VueCarousel-pagination {
|
||||
bottom: 10px;
|
||||
position: absolute;
|
||||
|
||||
display: none;
|
||||
|
||||
button:focus,
|
||||
button:active {
|
||||
outline: none;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
body {
|
||||
display: none;
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
.container-margin {
|
||||
|
|
@ -463,8 +461,6 @@ header #search-form > *:focus {
|
|||
.main-content-wrapper {
|
||||
@extend .fs14;
|
||||
|
||||
margin: 0;
|
||||
margin-bottom: 60px;
|
||||
display: inline-block;
|
||||
|
||||
> .row {
|
||||
|
|
@ -714,6 +710,10 @@ body::after {
|
|||
max-width: 1300px !important;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.remove-padding-margin {
|
||||
width: 100% !important;
|
||||
margin: 0px !important;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
min-height: 290px;
|
||||
}
|
||||
}
|
||||
|
||||
/* medium devices */
|
||||
|
|
@ -143,7 +147,7 @@
|
|||
|
||||
.badge-wrapper,
|
||||
.badge-container {
|
||||
top: -2px;
|
||||
top: -32px;
|
||||
left: -12px;
|
||||
position: relative;
|
||||
|
||||
|
|
@ -987,6 +991,10 @@
|
|||
position: absolute;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
min-height: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
/* medium devices */
|
||||
|
|
@ -1057,6 +1065,10 @@
|
|||
.product-card-new {
|
||||
max-width: 18rem;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
min-height: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
/* small devices */
|
||||
|
|
@ -1069,6 +1081,22 @@
|
|||
position: unset;
|
||||
top: unset;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.advertisement-four-container {
|
||||
min-height: 992px;
|
||||
|
||||
.advertisement-container-block {
|
||||
min-height: 425px;
|
||||
}
|
||||
|
||||
.offers-ct-panel {
|
||||
min-height: 425px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* very small devices */
|
||||
|
|
@ -1085,4 +1113,20 @@
|
|||
.quick-view-in-list {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.advertisement-four-container {
|
||||
min-height: 992px;
|
||||
|
||||
.advertisement-container-block {
|
||||
min-height: 425px;
|
||||
}
|
||||
|
||||
.offers-ct-panel {
|
||||
min-height: 425px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -890,11 +890,12 @@ button[disabled] {
|
|||
}
|
||||
|
||||
.modal-parent {
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 5000;
|
||||
position: fixed;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: rgba(256, 256, 256, 0.9);
|
||||
z-index: 125;
|
||||
}
|
||||
|
||||
.compare-icon,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
}
|
||||
|
||||
.material-icons {
|
||||
max-width: 30px;
|
||||
overflow: hidden;
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
|
@ -60,6 +62,8 @@
|
|||
}
|
||||
|
||||
.material-icons-outlined {
|
||||
max-width: 30px;
|
||||
overflow: hidden;
|
||||
font-family: 'Material Icons Outlined';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'إضافة منتج إلى قائمة الأمنيات',
|
||||
'remove-wishlist-text' => 'أزل المنتج من قائمة الأمنيات'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'في تقدم',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Produkt zur Wunschliste hinzufügen',
|
||||
'remove-wishlist-text' => 'Produkt von der Wunschliste entfernen'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'Im Gange',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Add product to wishlist',
|
||||
'remove-wishlist-text' => 'Remove product from wishlist'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'In Progress',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Agregar producto a la lista de deseos',
|
||||
'remove-wishlist-text' => 'Eliminar producto de la lista de deseos'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'En curso',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -300,7 +300,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'محصول را به لیست دلخواه اضافه کنید',
|
||||
'remove-wishlist-text' => 'محصول را از لیست دلخواه حذف کنید'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'در حال پیش رفت',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -322,6 +322,10 @@ return [
|
|||
'add-wishlist-text' => 'Ajouter un produit à la liste de souhaits',
|
||||
'remove-wishlist-text' => 'Supprimer le produit de la liste de souhaits',
|
||||
],
|
||||
|
||||
'overlay-loader' => [
|
||||
'message' => 'En cours',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -303,7 +303,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Aggiungi prodotto a wishlist',
|
||||
'remove-wishlist-text' => 'Rimuovi prodotti da wishlist'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'In corso',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -299,7 +299,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => '製品をウィッシュリストに追加',
|
||||
'remove-wishlist-text' => 'ウィッシュリストから商品を削除',
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => '進行中',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Toevoegen aan verlanglijst',
|
||||
'remove-wishlist-text' => 'Remove product from wishlist'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'Bezig',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -299,7 +299,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Dodaj produkt do listy wyboru',
|
||||
'remove-wishlist-text' => 'Usuń produkt z listy wyboru'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'W trakcie',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -303,6 +303,9 @@ return [
|
|||
'add-wishlist-text' => 'Adicionar produto à lista de desejos',
|
||||
'remove-wishlist-text' => 'Remover produto da lista de desejos',
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'Em progresso',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
|
|
@ -298,7 +298,10 @@ return [
|
|||
'wishlist' => [
|
||||
'add-wishlist-text' => 'Ürünü dilek listenize ekleyin',
|
||||
'remove-wishlist-text' => 'Ürünü dilek listenizden kaldırın'
|
||||
]
|
||||
],
|
||||
'overlay-loader' => [
|
||||
'message' => 'Devam etmekte',
|
||||
],
|
||||
],
|
||||
|
||||
'responsive' => [
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue