checkout process

This commit is contained in:
rahul shukla 2018-09-13 16:46:47 +05:30
commit 87e5e9a2bc
34 changed files with 1112 additions and 152 deletions

View File

@ -12,6 +12,7 @@
"dimsav/laravel-translatable": "^9.0",
"fideloper/proxy": "^4.0",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
"laravel/framework": "5.6.*",
"laravel/tinker": "^1.0",

221
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ee788a0a8a86526cd58b0b4853a45c06",
"content-hash": "c0c2a23aa2502c590b2ccf7975329ce1",
"packages": [
{
"name": "commerceguys/intl",
@ -600,6 +600,59 @@
],
"time": "2018-05-29T14:19:03+00:00"
},
{
"name": "intervention/imagecache",
"version": "2.3.3",
"source": {
"type": "git",
"url": "https://github.com/Intervention/imagecache.git",
"reference": "7936b90e695daee1aafbd25221815352ef97bcbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/imagecache/zipball/7936b90e695daee1aafbd25221815352ef97bcbc",
"reference": "7936b90e695daee1aafbd25221815352ef97bcbc",
"shasum": ""
},
"require": {
"illuminate/cache": "~4|~5",
"illuminate/filesystem": "~4|~5",
"intervention/image": "dev-master|~2,>=2.2.0",
"jeremeamia/superclosure": "~1|~2",
"php": ">=5.3.0"
},
"require-dev": {
"mockery/mockery": "~0.9.2",
"phpunit/phpunit": "3.*"
},
"type": "library",
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@olivervogel.net",
"homepage": "http://olivervogel.net/"
}
],
"description": "Caching extension for the Intervention Image Class",
"homepage": "http://image.intervention.io",
"keywords": [
"cache",
"gd",
"image",
"imagick",
"laravel"
],
"time": "2015-09-22T15:22:47+00:00"
},
{
"name": "jakub-onderka/php-console-color",
"version": "0.1",
@ -752,6 +805,64 @@
],
"time": "2018-05-16T11:53:55+00:00"
},
{
"name": "jeremeamia/SuperClosure",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/jeremeamia/super_closure.git",
"reference": "5707d5821b30b9a07acfb4d76949784aaa0e9ce9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/5707d5821b30b9a07acfb4d76949784aaa0e9ce9",
"reference": "5707d5821b30b9a07acfb4d76949784aaa0e9ce9",
"shasum": ""
},
"require": {
"nikic/php-parser": "^1.2|^2.0|^3.0|^4.0",
"php": ">=5.4",
"symfony/polyfill-php56": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
}
},
"autoload": {
"psr-4": {
"SuperClosure\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia",
"role": "Developer"
}
],
"description": "Serialize Closure objects, including their context and binding",
"homepage": "https://github.com/jeremeamia/super_closure",
"keywords": [
"closure",
"function",
"lambda",
"parser",
"serializable",
"serialize",
"tokenizer"
],
"time": "2018-03-21T22:21:57+00:00"
},
{
"name": "kalnoy/nestedset",
"version": "v4.3.2",
@ -2580,6 +2691,62 @@
],
"time": "2018-04-26T10:06:28+00:00"
},
{
"name": "symfony/polyfill-php56",
"version": "v1.9.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php56.git",
"reference": "7b4fc009172cc0196535b0328bd1226284a28000"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/7b4fc009172cc0196535b0328bd1226284a28000",
"reference": "7b4fc009172cc0196535b0328bd1226284a28000",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-util": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php56\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"time": "2018-08-06T14:22:27+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.8.0",
@ -2635,6 +2802,58 @@
],
"time": "2018-04-26T10:06:28+00:00"
},
{
"name": "symfony/polyfill-util",
"version": "v1.9.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-util.git",
"reference": "8e15d04ba3440984d23e7964b2ee1d25c8de1581"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8e15d04ba3440984d23e7964b2ee1d25c8de1581",
"reference": "8e15d04ba3440984d23e7964b2ee1d25c8de1581",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Util\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony utilities for portability of PHP codes",
"homepage": "https://symfony.com",
"keywords": [
"compat",
"compatibility",
"polyfill",
"shim"
],
"time": "2018-08-06T14:22:27+00:00"
},
{
"name": "symfony/process",
"version": "v4.1.2",

View File

@ -242,7 +242,8 @@ return [
'View' => Illuminate\Support\Facades\View::class,
'Datagrid' => Webkul\Ui\DataGrid\Facades\DataGrid::class,
'ProductGrid' => Webkul\Ui\DataGrid\Facades\ProductGrid::class,
'Image' => Intervention\Image\Facades\Image::class
'Image' => Intervention\Image\Facades\Image::class,
'Core' => Webkul\Core\Facades\Core::class
],
];

View File

@ -51,7 +51,7 @@ return [
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/public/storage',
'url' => env('APP_URL') . '/public/storage',
'visibility' => 'public',
],

72
config/imagecache.php Normal file
View File

@ -0,0 +1,72 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Name of route
|--------------------------------------------------------------------------
|
| Enter the routes name to enable dynamic imagecache manipulation.
| This handle will define the first part of the URI:
|
| {route}/{template}/{filename}
|
| Examples: "images", "img/cache"
|
*/
'route' => 'cache',
/*
|--------------------------------------------------------------------------
| Storage paths
|--------------------------------------------------------------------------
|
| The following paths will be searched for the image filename, submited
| by URI.
|
| Define as many directories as you like.
|
*/
'paths' => array(
storage_path('app/public'),
public_path('storage')
),
/*
|--------------------------------------------------------------------------
| Manipulation templates
|--------------------------------------------------------------------------
|
| Here you may specify your own manipulation filter templates.
| The keys of this array will define which templates
| are available in the URI:
|
| {route}/{template}/{filename}
|
| The values of this array will define which filter class
| will be applied, by its fully qualified name.
|
*/
'templates' => array(
'small' => 'Webkul\Product\CacheFilters\Small',
'medium' => 'Webkul\Product\CacheFilters\Medium',
'large' => 'Webkul\Product\CacheFilters\Large',
),
/*
|--------------------------------------------------------------------------
| Image Cache Lifetime
|--------------------------------------------------------------------------
|
| Lifetime in minutes of the images handled by the imagecache route.
|
*/
'lifetime' => 1,
// 'lifetime' => 43200,
);

244
config/repository.php Normal file
View File

@ -0,0 +1,244 @@
<?php
/*
|--------------------------------------------------------------------------
| Prettus Repository Config
|--------------------------------------------------------------------------
|
|
*/
return [
/*
|--------------------------------------------------------------------------
| Repository Pagination Limit Default
|--------------------------------------------------------------------------
|
*/
'pagination' => [
'limit' => 15
],
/*
|--------------------------------------------------------------------------
| Fractal Presenter Config
|--------------------------------------------------------------------------
|
Available serializers:
ArraySerializer
DataArraySerializer
JsonApiSerializer
*/
'fractal' => [
'params' => [
'include' => 'include'
],
'serializer' => League\Fractal\Serializer\DataArraySerializer::class
],
/*
|--------------------------------------------------------------------------
| Cache Config
|--------------------------------------------------------------------------
|
*/
'cache' => [
/*
|--------------------------------------------------------------------------
| Cache Status
|--------------------------------------------------------------------------
|
| Enable or disable cache
|
*/
'enabled' => false,
/*
|--------------------------------------------------------------------------
| Cache Minutes
|--------------------------------------------------------------------------
|
| Time of expiration cache
|
*/
'minutes' => 30,
/*
|--------------------------------------------------------------------------
| Cache Repository
|--------------------------------------------------------------------------
|
| Instance of Illuminate\Contracts\Cache\Repository
|
*/
'repository' => 'cache',
/*
|--------------------------------------------------------------------------
| Cache Clean Listener
|--------------------------------------------------------------------------
|
|
|
*/
'clean' => [
/*
|--------------------------------------------------------------------------
| Enable clear cache on repository changes
|--------------------------------------------------------------------------
|
*/
'enabled' => true,
/*
|--------------------------------------------------------------------------
| Actions in Repository
|--------------------------------------------------------------------------
|
| create : Clear Cache on create Entry in repository
| update : Clear Cache on update Entry in repository
| delete : Clear Cache on delete Entry in repository
|
*/
'on' => [
'create' => true,
'update' => true,
'delete' => true,
]
],
'params' => [
/*
|--------------------------------------------------------------------------
| Skip Cache Params
|--------------------------------------------------------------------------
|
|
| Ex: http://prettus.local/?search=lorem&skipCache=true
|
*/
'skipCache' => 'skipCache'
],
/*
|--------------------------------------------------------------------------
| Methods Allowed
|--------------------------------------------------------------------------
|
| methods cacheable : all, paginate, find, findByField, findWhere, getByCriteria
|
| Ex:
|
| 'only' =>['all','paginate'],
|
| or
|
| 'except' =>['find'],
*/
'allowed' => [
'only' => null,
'except' => null
]
],
/*
|--------------------------------------------------------------------------
| Criteria Config
|--------------------------------------------------------------------------
|
| Settings of request parameters names that will be used by Criteria
|
*/
'criteria' => [
/*
|--------------------------------------------------------------------------
| Accepted Conditions
|--------------------------------------------------------------------------
|
| Conditions accepted in consultations where the Criteria
|
| Ex:
|
| 'acceptedConditions'=>['=','like']
|
| $query->where('foo','=','bar')
| $query->where('foo','like','bar')
|
*/
'acceptedConditions' => [
'=',
'like'
],
/*
|--------------------------------------------------------------------------
| Request Params
|--------------------------------------------------------------------------
|
| Request parameters that will be used to filter the query in the repository
|
| Params :
|
| - search : Searched value
| Ex: http://prettus.local/?search=lorem
|
| - searchFields : Fields in which research should be carried out
| Ex:
| http://prettus.local/?search=lorem&searchFields=name;email
| http://prettus.local/?search=lorem&searchFields=name:like;email
| http://prettus.local/?search=lorem&searchFields=name:like
|
| - filter : Fields that must be returned to the response object
| Ex:
| http://prettus.local/?search=lorem&filter=id,name
|
| - orderBy : Order By
| Ex:
| http://prettus.local/?search=lorem&orderBy=id
|
| - sortedBy : Sort
| Ex:
| http://prettus.local/?search=lorem&orderBy=id&sortedBy=asc
| http://prettus.local/?search=lorem&orderBy=id&sortedBy=desc
|
| - searchJoin: Specifies the search method (AND / OR), by default the
| application searches each parameter with OR
| EX:
| http://prettus.local/?search=lorem&searchJoin=and
| http://prettus.local/?search=lorem&searchJoin=or
|
*/
'params' => [
'search' => 'search',
'searchFields' => 'searchFields',
'filter' => 'filter',
'orderBy' => 'orderBy',
'sortedBy' => 'sortedBy',
'with' => 'with',
'searchJoin' => 'searchJoin'
]
],
/*
|--------------------------------------------------------------------------
| Generator Config
|--------------------------------------------------------------------------
|
*/
'generator' => [
'basePath' => app()->path(),
'rootNamespace' => 'App\\',
'stubsOverridePath' => app()->path(),
'paths' => [
'models' => 'Entities',
'repositories' => 'Repositories',
'interfaces' => 'Repositories',
'transformers' => 'Transformers',
'presenters' => 'Presenters',
'validators' => 'Validators',
'controllers' => 'Http/Controllers',
'provider' => 'RepositoryServiceProvider',
'criteria' => 'Criteria'
]
]
];

View File

@ -108,6 +108,12 @@ class EventServiceProvider extends ServiceProvider
Event::listen('admin.acl.build', function ($acl) {
$acl->add('dashboard', 'Dashboard', 'admin.dashboard.index', 1);
$acl->add('catalog', 'Catalog', 'admin.catalog.index', 2);
$acl->add('catalog.products', 'Products', 'admin.catalog.products.index', 1);
$acl->add('catalog.categories', 'Categories', 'admin.catalog.categories.index', 1);
$acl->add('configuration', 'Configure', 'admin.account.edit', 5);
$acl->add('settings', 'Settings', 'admin.users.index', 6);

View File

@ -1,17 +1,12 @@
<?php
namespace Webkul\Core\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
use Illuminate\Routing\Router;
use Illuminate\Foundation\AliasLoader;
use Webkul\Core\Http\Middleware\Locale;
use Webkul\User\Http\Middleware\RedirectIfNotAdmin;
use Webkul\Customer\Http\Middleware\RedirectIfNotCustomer;
use Webkul\Core\Core;
use Webkul\Core\Facades\CoreFacade;
class CoreServiceProvider extends ServiceProvider
{
/**
@ -22,26 +17,15 @@ class CoreServiceProvider extends ServiceProvider
public function boot(Router $router)
{
include __DIR__ . '/../Http/helpers.php';
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'core');
$router->aliasMiddleware('locale', Locale::class);
$router->aliasMiddleware('admin', RedirectIfNotAdmin::class);
$router->aliasMiddleware('customer', RedirectIfNotCustomer::class);
$this->publishes([
__DIR__ . '/../../publishable/lang' => public_path('vendor/webkul/core/lang'),
], 'public');
// $this->publishes([
// __DIR__ . '/../../publishable/lang' => public_path('vendor/webkul/core/lang'),
// ], 'public');
Validator::extend('slug', 'Webkul\Core\Contracts\Validations\Slug@passes');
Validator::extend('code', 'Webkul\Core\Contracts\Validations\Code@passes');
}
/**
* Register services.
*
@ -51,7 +35,6 @@ class CoreServiceProvider extends ServiceProvider
{
$this->registerFacades();
}
/**
* Register Bouncer as a singleton.
*
@ -61,7 +44,6 @@ class CoreServiceProvider extends ServiceProvider
{
$loader = AliasLoader::getInstance();
$loader->alias('core', CoreFacade::class);
$this->app->singleton('core', function () {
return new Core();
});

View File

@ -13,10 +13,6 @@ class CustomerServiceProvider extends ServiceProvider
{
public function boot(Router $router)
{
$this->publishes([
__DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/customer/assets'),
], 'public');
$router->aliasMiddleware('customer', RedirectIfNotCustomer::class);
$this->loadMigrationsFrom(__DIR__ . '/../Database/migrations');

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Product\CacheFilters;
use Intervention\Image\Image;
use Intervention\Image\Filters\FilterInterface;
class Large implements FilterInterface
{
public function applyFilter(Image $image)
{
return $image->resize(480, 480);
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Product\CacheFilters;
use Intervention\Image\Image;
use Intervention\Image\Filters\FilterInterface;
class Medium implements FilterInterface
{
public function applyFilter(Image $image)
{
return $image->resize(280, 350);
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Product\CacheFilters;
use Intervention\Image\Image;
use Intervention\Image\Filters\FilterInterface;
class Small implements FilterInterface
{
public function applyFilter(Image $image)
{
return $image->resize(120, 120);
}
}

View File

@ -3,7 +3,7 @@
namespace Webkul\Product\Product;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
use Webkul\Product\Product\Gallery;
use Webkul\Product\Product\ProductImage;
use Webkul\Product\Product\Price;
class ConfigurableOption extends AbstractProduct
@ -16,11 +16,11 @@ class ConfigurableOption extends AbstractProduct
protected $attributeOption;
/**
* Gallery object
* ProductImage object
*
* @var array
*/
protected $gallery;
protected $productImage;
/**
* Price object
@ -33,19 +33,19 @@ class ConfigurableOption extends AbstractProduct
* Create a new controller instance.
*
* @param Webkul\Attribute\Repositories\AttributeOptionRepository $attributeOption
* @param Webkul\Product\Product\Gallery $gallery
* @param Webkul\Product\Product\ProductImage $productImage
* @param Webkul\Product\Product\Price $price
* @return void
*/
public function __construct(
AttributeOption $attributeOption,
Gallery $gallery,
ProductImage $productImage,
Price $price
)
{
$this->attributeOption = $attributeOption;
$this->gallery = $gallery;
$this->productImage = $productImage;
$this->price = $price;
}
@ -82,6 +82,10 @@ class ConfigurableOption extends AbstractProduct
$config = [
'attributes' => $this->getAttributesData($product, $options),
'index' => isset($options['index']) ? $options['index'] : [],
'regular_price' => [
'formated_price' => core()->currency($this->price->getMinimalPrice($product)),
'price' => $this->price->getMinimalPrice($product)
],
'variant_prices' => $this->getVariantPrices($product),
'variant_images' => $this->getVariantImages($product),
'chooseText' => trans('shop::app.products.choose-option')
@ -201,8 +205,14 @@ class ConfigurableOption extends AbstractProduct
foreach ($this->getAllowProducts($product) as $variant) {
$prices[$variant->id] = [
'regular_price' => $variant->price,
'final_price' => $this->price->getMinimalPrice($variant),
'regular_price' => [
'formated_price' => core()->currency($variant->price),
'price' => $variant->price
],
'final_price' => [
'formated_price' => core()->currency($this->price->getMinimalPrice($variant)),
'price' => $this->price->getMinimalPrice($variant)
]
];
}
@ -220,7 +230,7 @@ class ConfigurableOption extends AbstractProduct
$images = [];
foreach ($this->getAllowProducts($product) as $variant) {
$images[$variant->id] = $this->gallery->getImages($variant);
$images[$variant->id] = $this->productImage->getGalleryImages($variant);
}
return $images;

View File

@ -1,25 +0,0 @@
<?php
namespace Webkul\Product\Product;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
class Gallery extends AbstractProduct
{
/**
* Retrieve collection of gallery images
*
* @param Product $product
* @return array
*/
public function getImages($product)
{
$images[] = [
'small_image_url' => '',
'medium_image_url' => '',
'large_image_url' => '',
];
return $images;
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Webkul\Product\Product;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
use Illuminate\Support\Facades\Storage;
class ProductImage extends AbstractProduct
{
/**
* Retrieve collection of gallery images
*
* @param Product $product
* @return array
*/
public function getGalleryImages($product)
{
$images = [];
foreach($product->images as $image) {
if(!Storage::has($image->path))
continue;
$images[] = [
'small_image_url' => url('cache/small/' . $image->path),
'medium_image_url' => url('cache/medium/' . $image->path),
'large_image_url' => url('cache/large/' . $image->path),
'original_image_url' => url('cache/original/' . $image->path),
];
}
if(!$product->parent_id && !count($images)) {
$images[] = [
'small_image_url' => bagisto_asset('images/product/small-product-placeholder.png'),
'medium_image_url' => bagisto_asset('images/product/meduim-product-placeholder.png'),
'large_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
'original_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
];
}
return $images;
}
/**
* Get product's base image
*
* @param Product $product
* @return array
*/
public function getProductBaseImage($product)
{
$images = $product->images;
if($images->count()) {
$image = [
'small_image_url' => url('cache/small/' . $images[0]->path),
'medium_image_url' => url('cache/medium/' . $images[0]->path),
'large_image_url' => url('cache/large/' . $images[0]->path),
'original_image_url' => url('cache/original/' . $images[0]->path),
];
} else {
$image = [
'small_image_url' => bagisto_asset('images/product/small-product-placeholder.png'),
'medium_image_url' => bagisto_asset('images/product/meduim-product-placeholder.png'),
'large_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
'original_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
];
}
return $image;
}
}

View File

@ -14,23 +14,6 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'shop::customers.checkout.index'
])->name('shop.checkout');
/* dummy routes */
Route::view('/customer/order','shop::customers.account.orders.index');
// Route::view('/customer/checkout','shop::customers.checkout.index');
Route::view('/customer/signin','shop::customers.checkout.signin');
Route::view('/customer/ship_method','shop::customers.checkout.ship-method');
Route::view('/customer/payment_method','shop::customers.checkout.payment-method');
Route::view('/customer/payment_complete','shop::customers.checkout.complete');
Route::view('/test','shop::index');
/* dummy routes ends here */
@ -52,6 +35,10 @@ Route::group(['middleware' => ['web']], function () {
'redirect' => 'shop.reviews.index'
])->name('shop.reviews.store');
Route::post('/reviews/create/{slug}', 'Webkul\Shop\Http\Controllers\ReviewController@store')->defaults('_config', [
'redirect' => 'admin.reviews.index'
])->name('admin.reviews.store');
// Route::post('/reviews/create/{slug}', 'Webkul\Core\Http\Controllers\ReviewController@store')->defaults('_config', [
// 'redirect' => 'admin.reviews.index'
// ])->name('admin.reviews.store');

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -800,10 +800,18 @@ section.slider-block {
.product-card {
.product-image img {
align-self: center;
width: 100%;
margin-bottom: 14px;
.product-image {
background: #F2F2F2;
margin-bottom: 10px;
// width: 380px;
// max-width: 100%;
// text-align: center;
img {
align-self: center;
width: 100%;
margin-bottom: 14px;
}
}
.product-name {
@ -1336,9 +1344,10 @@ section.product-detail {
}
div.layouter {
display:flex;
flex-flow: row;
margin-top: 21px;
margin-top: 20px;
margin-bottom: 20px;
display: inline-block;
width: 100%;
.mixed-group {
@ -1453,20 +1462,74 @@ section.product-detail {
}
div.product-image-group {
display:flex;
flex-direction: row;
justify-content: flex-start;
margin-right: 2.5%;
width: 43%;
float: left;
min-height: 1px;
position: relative;
.side-group {
.thumb-list {
display: flex;
flex-direction: column;
margin-right: 4px;
height: 480px;
overflow: hidden;
position: relative;
float: left;
.thumb-frame {
border: 2px solid transparent;
background: #F2F2F2;
width: 120px;
height: 120px;
&.active {
border-color: #979797;
}
img {
width: 100%;
height: 100%;
}
}
.gallery-control {
width: 100%;
position: absolute;
text-align: center;
cursor: pointer;
z-index: 1;
.overlay {
opacity: 0.3;
background: #000000;
width: 100%;
height: 18px;
position: absolute;
left: 0;
z-index: -1;
}
.icon {
z-index: 2;
}
&.top {
top: 0;
}
&.bottom {
bottom: 0;
}
}
}
.product-hero-image {
display: block;
position: relative;
background: #F2F2F2;
width: 480px;
max-height: 480px;
float: left;
.wishlist {
position: absolute;
@ -1483,6 +1546,9 @@ section.product-detail {
}
.details {
width: 57%;
float: left;
.product-price {
margin-bottom: 14px;
}

View File

@ -1,7 +1,12 @@
<div class="product-card">
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
<?php $productBaseImage = $productImageHelper->getProductBaseImage($product); ?>
<div class="product-image">
<a href="{{ route('shop.products.index', $product->url_key) }}" title="{{ $product->name }}">
<img src="{{ bagisto_asset('images/gogs.png') }}" />
<img src="{{ $productBaseImage['medium_image_url'] }}" />
</a>
</div>

View File

@ -6,7 +6,7 @@
<span class="price-label">{{ __('shop::app.products.price-label') }}</span>
<span>{{ core()->currency($priceHelper->getMinimalPrice($product)) }}</span>
<span class="final-price">{{ core()->currency($priceHelper->getMinimalPrice($product)) }}</span>
@else

View File

@ -10,13 +10,11 @@
<div class="layouter">
<form action="" style="display: inherit;">
<form action="">
@csrf()
<input type="hidden" name="product">
<input type="hidden" name="selected_configurable_option">
@include ('shop::products.view.gallery')

View File

@ -2,7 +2,6 @@
@inject ('configurableOptionHelper', 'Webkul\Product\Product\ConfigurableOption')
<product-options></product-options>
@push('scripts')
@ -10,39 +9,56 @@
<script type="text/x-template" id="product-options-template">
<div class="attributes">
<input type="hidden" name="selected_configurable_option" :value="selectedProductId">
<div v-for='(attribute, index) in childAttributes' class="attribute control-group" :class="[errors.has('super_attribute[' + attribute.id + ']') ? 'has-error' : '']">
<label class="reqiured">@{{ attribute.label }}</label>
<select v-validate="'required'" class="control" :name="['super_attribute[' + attribute.id + ']']" :disabled="attribute.disabled" @change="configure(attribute, $event.target.value)">
<select v-validate="'required'" class="control" :name="['super_attribute[' + attribute.id + ']']" :disabled="attribute.disabled" @change="configure(attribute, $event.target.value)" :id="['attribute_' + attribute.id]">
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
</select>
<span class="control-error" v-if="errors.has('super_attribute[' + attribute.id + ']')">@{{ errors.first('super_attribute[' + attribute.id + ']') }}</span>
<span class="control-error" v-if="errors.has('super_attribute[' + attribute.id + ']')">
@{{ errors.first('super_attribute[' + attribute.id + ']') }}
</span>
</div>
</div>
</script>
<?php $config = $configurableOptionHelper->getConfigurationConfig($product) ?>
<script>
Vue.component('product-options', {
template: '#product-options-template',
data: () => ({
config: @json($configurableOptionHelper->getConfigurationConfig($product)),
childAttributes: []
config: @json($config),
childAttributes: [],
selectedProductId: '',
simpleProduct: null,
galleryImages: []
}),
created () {
this.galleryImages = galleryImages.slice(0)
var config = @json($config);
var childAttributes = this.childAttributes,
attributes = this.config.attributes,
attributes = config.attributes.slice(),
index = attributes.length,
attribute;
while (index--) {
// attribute = Object.assign({}, attributes[index]);
attribute = attributes[index];
attribute.options = [];
@ -65,32 +81,68 @@
methods: {
configure (attribute, value) {
// this.simpleProduct = this._getSimpleProductId(attribute);
this.simpleProduct = this.getSelectedProductId(attribute, value);
if (value) {
attribute.selectedIndex = this.getSelectedIndex(attribute, value);
if (attribute.nextAttribute) {
attribute.nextAttribute.disabled = false;
this.fillSelect(attribute.nextAttribute);
this.resetChildren(attribute.nextAttribute);
} else {
//Set product id hidden value
this.selectedProductId = attribute.options[attribute.selectedIndex].allowedProducts[0];
}
} else {
attribute.selectedIndex = 0;
this.resetChildren(attribute);
this.clearSelect(attribute.nextAttribute)
}
// this.reloadPrice();
// this.changeProductImage();
this.reloadPrice();
this.changeProductImages();
},
getSelectedIndex (attribute, value) {
var selectedIndex = 0;
attribute.options.forEach(function(option, index) {
if(option.id == value) {
selectedIndex = index;
}
})
return selectedIndex;
},
getSelectedProductId (attribute, value) {
var options = attribute.options,
matchedOptions;
matchedOptions = options.filter(function (option) {
return option.id == value;
});
if(matchedOptions[0] != undefined && matchedOptions[0].allowedProducts != undefined) {
return matchedOptions[0].allowedProducts[0];
}
return undefined;
},
fillSelect (attribute) {
var options = this.getAttributeOptions(attribute.id),
prevOption,
index = 1,
products,
allowedProducts,
i,
j;
this.clearSelect(attribute)
attribute.options = [];
attribute.options[0] = {'id': '', 'label': this.config.chooseText, 'products': []};
@ -98,25 +150,23 @@
prevOption = attribute.prevAttribute.options[attribute.prevAttribute.selectedIndex];
}
// console.log(attribute)
if (options) {
for (i = 0; i < options.length; i++) {
products = [];
allowedProducts = [];
if (prevOption) {
for (j = 0; j < options[i].products.length; j++) {
if (prevOption.products &&
prevOption.products.indexOf(options[i].products[j]) > -1) {
products.push(options[i].products[j]);
if (prevOption.products && prevOption.products.indexOf(options[i].products[j]) > -1) {
allowedProducts.push(options[i].products[j]);
}
}
} else {
products = options[i].products.slice(0);
allowedProducts = options[i].products.slice(0);
}
if (products.length > 0) {
options[i].products = products;
if (allowedProducts.length > 0) {
options[i].allowedProducts = allowedProducts;
attribute.options[index] = options[i];
index++;
@ -133,12 +183,22 @@
});
}
},
clearSelect: function (attribute) {
if(!attribute)
return;
var element = document.getElementById("attribute_" + attribute.id);
if(element) {
element.selectedIndex = "0";
}
},
getAttributeOptions (attributeId) {
var this_this = this,
options;
this.config.attributes.forEach(function(attribute, index) {
if (attribute.id == attributeId) {
options = attribute.options;
@ -149,11 +209,40 @@
},
reloadPrice () {
var selectedOptionCount = 0;
this.childAttributes.forEach(function(attribute) {
if(attribute.selectedIndex) {
selectedOptionCount++;
}
});
var priceLabelElement = document.querySelector('.price-label');
var priceElement = document.querySelector('.final-price');
if(this.childAttributes.length == selectedOptionCount) {
priceLabelElement.style.display = 'none';
priceElement.innerHTML = this.config.variant_prices[this.simpleProduct].final_price.formated_price;
} else {
priceLabelElement.style.display = 'inline-block';
priceElement.innerHTML = this.config.regular_price.formated_price;
}
},
changeProductImage () {
changeProductImages () {
galleryImages.splice(0, galleryImages.length)
this.galleryImages.forEach(function(image) {
galleryImages.push(image)
});
if(this.simpleProduct) {
this.config.variant_images[this.simpleProduct].forEach(function(image) {
galleryImages.unshift(image)
});
}
},
}

View File

@ -1,16 +1,106 @@
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
<?php $images = $productImageHelper->getGalleryImages($product); ?>
<div class="product-image-group">
<div class="side-group">
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
</div>
<product-gallery></product-gallery>
<div class="product-hero-image" id="product-hero-image">
<img src="{{ bagisto_asset('images/jeans_big.jpg') }}" />
<img class="wishlist" src="{{ bagisto_asset('images/wish.svg') }}" />
<img class="share" src="{{ bagisto_asset('images/icon-share.svg') }}" />
</div>
@include ('shop::products.add-to')
</div>
</div>
@push('scripts')
<script type="text/x-template" id="product-gallery-template">
<div>
<ul class="thumb-list">
<li class="gallery-control top" @click="moveThumbs('top')" v-if="thumbs.length > 4">
<span class="overlay"></span>
<i class="icon arrow-up-white-icon"></i>
</li>
<li class="thumb-frame" v-for='(thumb, index) in thumbs' @click="changeImage(thumb)" :class="[thumb.large_image_url == currentLargeImageUrl ? 'active' : '']">
<img :src="thumb.small_image_url" />
</li>
<li class="gallery-control bottom" @click="moveThumbs('bottom')" v-if="thumbs.length > 4">
<span class="overlay"></span>
<i class="icon arrow-down-white-icon"></i>
</li>
</ul>
<div class="product-hero-image" id="product-hero-image">
<img :src="currentLargeImageUrl" />
</div>
</div>
</script>
<script>
var galleryImages = @json($images);
Vue.component('product-gallery', {
template: '#product-gallery-template',
data: () => ({
images: galleryImages,
thumbs: [],
currentLargeImageUrl: ''
}),
watch: {
'images': function(newVal, oldVal) {
this.changeImage(this.images[0])
this.prepareThumbs()
}
},
created () {
console.log(this.images[0])
this.changeImage(this.images[0])
this.prepareThumbs()
},
methods: {
prepareThumbs () {
var this_this = this;
this_this.thumbs = [];
this.images.forEach(function(image) {
this_this.thumbs.push(image);
});
},
changeImage (image) {
this.currentLargeImageUrl = image.large_image_url;
},
moveThumbs(direction) {
let len = this.thumbs.length;
if (direction === "top") {
const moveThumb = this.thumbs.splice(len - 1, 1);
this.thumbs = [moveThumb[0], ...this.thumbs];
} else {
const moveThumb = this.thumbs.splice(0, 1);
this.thumbs = [...this.thumbs, moveThumb[0]];
}
},
}
});
</script>
@endpush

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="8px" viewBox="0 0 12 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>down-arrow</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="down-arrow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="" fill="#FFFFFF" transform="translate(6.000000, 4.519196) rotate(-270.000000) translate(-6.000000, -4.519196) " points="3.48080444 8.51919556 6.54690552 4.51919556 3.48080444 0.519195557 5.48550415 0.519195557 8.51919556 4.51919556 5.48550415 8.51919556"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 741 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="8px" viewBox="0 0 12 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>up-arrow</title>
<desc>Created with Sketch.</desc>
<defs>
<polygon id="path-1" points="3.48080444 7.51919556 6.54690552 3.51919556 3.48080444 -0.480804443 5.48550415 -0.480804443 8.51919556 3.51919556 5.48550415 7.51919556"></polygon>
</defs>
<g id="up-arrow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="" fill="#FFFFFF" transform="translate(6.000000, 3.519196) scale(1, -1) rotate(-270.000000) translate(-6.000000, -3.519196) " xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 911 B

View File

@ -993,6 +993,7 @@ h2 {
background-image: url("../images/placeholder-icon.svg");
background-repeat: no-repeat;
background-position: center;
margin-bottom: 20px;
img.preview {
width: 100%;

View File

@ -168,6 +168,18 @@
height: 24px;
}
.arrow-down-white-icon {
background-image: url("../images/down-arrow-white.svg");
width: 17px;
height: 13px;
}
.arrow-up-white-icon {
background-image: url("../images/up-arrow-white.svg");
width: 17px;
height: 13px;
}
.active {
.dashboard-icon {
background-image: url("../images/Icon-Dashboard-Active.svg");

View File

@ -4,6 +4,20 @@ namespace Webkul\User;
class Bouncer
{
/**
* Checks if user has permission for certain action
*
* @param String $permission
* @return Void
*/
public static function hasPermission($permission)
{
if(!auth()->check() || !auth()->user()->hasPermission($permission))
return false;
return true;
}
/**
* Checks if user allowed or not for certain action
*

View File

@ -849,6 +849,11 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
justify-content: center;
}
.main-container-wrapper .product-card .product-image {
background: #F2F2F2;
margin-bottom: 10px;
}
.main-container-wrapper .product-card .product-image img {
-ms-flex-item-align: center;
align-self: center;
@ -1409,14 +1414,10 @@ section.product-detail div.category-breadcrumbs {
}
section.product-detail div.layouter {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-flow: row;
flex-flow: row;
margin-top: 21px;
margin-top: 20px;
margin-bottom: 20px;
display: inline-block;
width: 100%;
}
section.product-detail div.layouter .mixed-group .single-image {
@ -1547,20 +1548,13 @@ section.product-detail div.layouter .rating-reviews .reviews .view-all {
}
section.product-detail div.layouter div.product-image-group {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
margin-right: 2.5%;
width: 43%;
float: left;
min-height: 1px;
position: relative;
}
section.product-detail div.layouter div.product-image-group .side-group {
section.product-detail div.layouter div.product-image-group .thumb-list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@ -1569,11 +1563,65 @@ section.product-detail div.layouter div.product-image-group .side-group {
-ms-flex-direction: column;
flex-direction: column;
margin-right: 4px;
height: 480px;
overflow: hidden;
position: relative;
float: left;
}
section.product-detail div.layouter div.product-image-group .thumb-list .thumb-frame {
border: 2px solid transparent;
background: #F2F2F2;
width: 120px;
height: 120px;
}
section.product-detail div.layouter div.product-image-group .thumb-list .thumb-frame.active {
border-color: #979797;
}
section.product-detail div.layouter div.product-image-group .thumb-list .thumb-frame img {
width: 100%;
height: 100%;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control {
width: 100%;
position: absolute;
text-align: center;
cursor: pointer;
z-index: 1;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control .overlay {
opacity: 0.3;
background: #000000;
width: 100%;
height: 18px;
position: absolute;
left: 0;
z-index: -1;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control .icon {
z-index: 2;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control.top {
top: 0;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control.bottom {
bottom: 0;
}
section.product-detail div.layouter div.product-image-group .product-hero-image {
display: block;
position: relative;
background: #F2F2F2;
width: 480px;
max-height: 480px;
float: left;
}
section.product-detail div.layouter div.product-image-group .product-hero-image .wishlist {
@ -1588,6 +1636,11 @@ section.product-detail div.layouter div.product-image-group .product-hero-image
right: 45px;
}
section.product-detail div.layouter .details {
width: 57%;
float: left;
}
section.product-detail div.layouter .details .product-price {
margin-bottom: 14px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB