Merge branch 'master' of https://github.com/bagisto/bagisto into development
This commit is contained in:
commit
25e3561897
|
|
@ -34,10 +34,12 @@ return [
|
|||
*/
|
||||
'storage' => [
|
||||
'enabled' => true,
|
||||
'driver' => 'file', // redis, file, pdo, custom
|
||||
'driver' => 'file', // redis, file, pdo, socket, custom
|
||||
'path' => storage_path('debugbar'), // For file driver
|
||||
'connection' => null, // Leave null for default connection (Redis/PDO)
|
||||
'provider' => '', // Instance of StorageInterface for custom driver
|
||||
'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver
|
||||
'port' => 2304, // Port to use with the "socket" driver
|
||||
],
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace Webkul\API\Http\Resources\Catalog;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Webkul\Product\Helpers\ProductType;
|
||||
|
||||
class Product extends JsonResource
|
||||
{
|
||||
|
|
@ -14,11 +13,13 @@ class Product extends JsonResource
|
|||
*/
|
||||
public function __construct($resource)
|
||||
{
|
||||
parent::__construct($resource);
|
||||
|
||||
$this->productImageHelper = app('Webkul\Product\Helpers\ProductImage');
|
||||
|
||||
$this->productReviewHelper = app('Webkul\Product\Helpers\Review');
|
||||
|
||||
parent::__construct($resource);
|
||||
$this->wishlistHelper = app('Webkul\Customer\Helpers\Wishlist');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -29,52 +30,264 @@ class Product extends JsonResource
|
|||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
/* assign product */
|
||||
$product = $this->product ? $this->product : $this;
|
||||
|
||||
$prices = $product->getTypeInstance()->getProductPrices();
|
||||
/* get type instance */
|
||||
$productTypeInstance = $product->getTypeInstance();
|
||||
|
||||
/* generating resource */
|
||||
return [
|
||||
/* product's information */
|
||||
'id' => $product->id,
|
||||
'sku' => $product->sku,
|
||||
'type' => $product->type,
|
||||
'name' => $this->name,
|
||||
'url_key' => $this->url_key,
|
||||
'price' => $product->getTypeInstance()->getMinimalPrice(),
|
||||
'formated_price' => core()->currency($product->getTypeInstance()->getMinimalPrice()),
|
||||
'short_description' => $this->short_description,
|
||||
'description' => $this->description,
|
||||
'sku' => $this->sku,
|
||||
'name' => $product->name,
|
||||
'url_key' => $product->url_key,
|
||||
'price' => $productTypeInstance->getMinimalPrice(),
|
||||
'formated_price' => core()->currency($productTypeInstance->getMinimalPrice()),
|
||||
'short_description' => $product->short_description,
|
||||
'description' => $product->description,
|
||||
'images' => ProductImage::collection($product->images),
|
||||
'base_image' => $this->productImageHelper->getProductBaseImage($product),
|
||||
'variants' => Self::collection($this->variants),
|
||||
'in_stock' => $product->haveSufficientQuantity(1),
|
||||
$this->mergeWhen($product->getTypeInstance()->isComposite(), [
|
||||
'super_attributes' => Attribute::collection($product->super_attributes),
|
||||
]),
|
||||
'special_price' => $this->when(
|
||||
$product->getTypeInstance()->haveSpecialPrice(),
|
||||
$product->getTypeInstance()->getSpecialPrice()
|
||||
),
|
||||
'formated_special_price' => $this->when(
|
||||
$product->getTypeInstance()->haveSpecialPrice(),
|
||||
core()->currency($product->getTypeInstance()->getSpecialPrice())
|
||||
),
|
||||
'regular_price' => $this->when(
|
||||
$product->getTypeInstance()->haveSpecialPrice(),
|
||||
data_get($prices, 'regular_price.price')
|
||||
),
|
||||
'formated_regular_price' => $this->when(
|
||||
$product->getTypeInstance()->haveSpecialPrice(),
|
||||
data_get($prices, 'regular_price.formated_price')
|
||||
),
|
||||
'created_at' => $product->created_at,
|
||||
'updated_at' => $product->updated_at,
|
||||
|
||||
/* product's reviews */
|
||||
'reviews' => [
|
||||
'total' => $total = $this->productReviewHelper->getTotalReviews($product),
|
||||
'total_rating' => $total ? $this->productReviewHelper->getTotalRating($product) : 0,
|
||||
'average_rating' => $total ? $this->productReviewHelper->getAverageRating($product) : 0,
|
||||
'percentage' => $total ? json_encode($this->productReviewHelper->getPercentageRating($product)) : [],
|
||||
],
|
||||
|
||||
/* product's checks */
|
||||
'in_stock' => $product->haveSufficientQuantity(1),
|
||||
'is_saved' => false,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
'is_wishlisted' => $this->wishlistHelper->getWishlistProduct($product),
|
||||
'is_item_in_cart' => \Cart::hasProduct($product),
|
||||
'show_quantity_changer' => $this->when(
|
||||
$product->type !== 'grouped',
|
||||
$product->getTypeInstance()->showQuantityBox()
|
||||
),
|
||||
|
||||
/* product's extra information */
|
||||
$this->merge($this->allProductExtraInfo()),
|
||||
|
||||
/* special price cases */
|
||||
$this->merge($this->specialPriceInfo()),
|
||||
|
||||
/* super attributes */
|
||||
$this->mergeWhen($productTypeInstance->isComposite(), [
|
||||
'super_attributes' => Attribute::collection($product->super_attributes),
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get special price information.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function specialPriceInfo()
|
||||
{
|
||||
$product = $this->product ? $this->product : $this;
|
||||
|
||||
$productTypeInstance = $product->getTypeInstance();
|
||||
|
||||
return [
|
||||
'special_price' => $this->when(
|
||||
$productTypeInstance->haveSpecialPrice(),
|
||||
$productTypeInstance->getSpecialPrice()
|
||||
),
|
||||
'formated_special_price' => $this->when(
|
||||
$productTypeInstance->haveSpecialPrice(),
|
||||
core()->currency($productTypeInstance->getSpecialPrice())
|
||||
),
|
||||
'regular_price' => $this->when(
|
||||
$productTypeInstance->haveSpecialPrice(),
|
||||
data_get($productTypeInstance->getProductPrices(), 'regular_price.price')
|
||||
),
|
||||
'formated_regular_price' => $this->when(
|
||||
$productTypeInstance->haveSpecialPrice(),
|
||||
data_get($productTypeInstance->getProductPrices(), 'regular_price.formated_price')
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all product's extra information.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function allProductExtraInfo()
|
||||
{
|
||||
$product = $this->product ? $this->product : $this;
|
||||
|
||||
$productTypeInstance = $product->getTypeInstance();
|
||||
|
||||
return [
|
||||
/* grouped product */
|
||||
$this->mergeWhen(
|
||||
$productTypeInstance instanceof \Webkul\Product\Type\Grouped,
|
||||
$product->type == 'grouped'
|
||||
? $this->getGroupedProductInfo($product)
|
||||
: null
|
||||
),
|
||||
|
||||
/* bundle product */
|
||||
$this->mergeWhen(
|
||||
$productTypeInstance instanceof \Webkul\Product\Type\Bundle,
|
||||
$product->type == 'bundle'
|
||||
? $this->getBundleProductInfo($product)
|
||||
: null
|
||||
),
|
||||
|
||||
/* configurable product */
|
||||
$this->mergeWhen(
|
||||
$productTypeInstance instanceof \Webkul\Product\Type\Configurable,
|
||||
$product->type == 'configurable'
|
||||
? $this->getConfigurableProductInfo($product)
|
||||
: null
|
||||
),
|
||||
|
||||
/* downloadable product */
|
||||
$this->mergeWhen(
|
||||
$productTypeInstance instanceof \Webkul\Product\Type\Downloadable,
|
||||
$product->type == 'downloadable'
|
||||
? $this->getDownloadableProductInfo($product)
|
||||
: null
|
||||
),
|
||||
|
||||
/* booking product */
|
||||
$this->mergeWhen(
|
||||
$product->type == 'booking',
|
||||
$product->type == 'booking'
|
||||
? $this->getBookingProductInfo($product)
|
||||
: null
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get grouped product's extra information.
|
||||
*
|
||||
* @param \Webkul\Product\Models\Product
|
||||
* @return array
|
||||
*/
|
||||
private function getGroupedProductInfo($product)
|
||||
{
|
||||
return [
|
||||
'grouped_products' => $product->grouped_products->map(function($groupedProduct) {
|
||||
$associatedProduct = $groupedProduct->associated_product;
|
||||
|
||||
$data = $associatedProduct->toArray();
|
||||
|
||||
return array_merge($data, [
|
||||
'qty' => $groupedProduct->qty,
|
||||
'isSaleable' => $associatedProduct->getTypeInstance()->isSaleable(),
|
||||
'formated_price' => $associatedProduct->getTypeInstance()->getPriceHtml(),
|
||||
'show_quantity_changer' => $associatedProduct->getTypeInstance()->showQuantityBox(),
|
||||
]);
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bundle product's extra information.
|
||||
*
|
||||
* @param \Webkul\Product\Models\Product
|
||||
* @return array
|
||||
*/
|
||||
private function getBundleProductInfo($product)
|
||||
{
|
||||
return [
|
||||
'currency_options' => core()->getAccountJsSymbols(),
|
||||
'bundle_options' => app('Webkul\Product\Helpers\BundleOption')->getBundleConfig($product)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configurable product's extra information.
|
||||
*
|
||||
* @param \Webkul\Product\Models\Product
|
||||
* @return array
|
||||
*/
|
||||
private function getConfigurableProductInfo($product)
|
||||
{
|
||||
return [
|
||||
'variants' => $product->variants
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get downloadable product's extra information.
|
||||
*
|
||||
* @param \Webkul\Product\Models\Product
|
||||
* @return array
|
||||
*/
|
||||
private function getDownloadableProductInfo($product)
|
||||
{
|
||||
return [
|
||||
'downloadable_links' => $product->downloadable_links->map(function ($downloadableLink) {
|
||||
$data = $downloadableLink->toArray();
|
||||
|
||||
if (isset($data['sample_file'])) {
|
||||
$data['price'] = core()->currency($downloadableLink->price);
|
||||
$data['sample_download_url'] = route('shop.downloadable.download_sample', ['type' => 'link', 'id' => $downloadableLink['id']]);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}),
|
||||
|
||||
'downloadable_samples' => $product->downloadable_samples->map(function ($downloadableSample) {
|
||||
$sample = $downloadableSample->toArray();
|
||||
$data = $sample;
|
||||
$data['download_url'] = route('shop.downloadable.download_sample', ['type' => 'sample', 'id' => $sample['id']]);
|
||||
return $data;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get booking product's extra information.
|
||||
*
|
||||
* @param \Webkul\Product\Models\Product
|
||||
* @return array
|
||||
*/
|
||||
private function getBookingProductInfo($product)
|
||||
{
|
||||
$bookingProduct = app('\Webkul\BookingProduct\Repositories\BookingProductRepository')->findOneByField('product_id', $product->id);
|
||||
|
||||
$data['slot_index_route'] = route('booking_product.slots.index', $bookingProduct->id);
|
||||
|
||||
if ($bookingProduct->type == 'appointment') {
|
||||
$bookingSlotHelper = app('\Webkul\BookingProduct\Helpers\AppointmentSlot');
|
||||
|
||||
$data['today_slots_html'] = $bookingSlotHelper->getTodaySlotsHtml($bookingProduct);
|
||||
$data['week_slot_durations'] = $bookingSlotHelper->getWeekSlotDurations($bookingProduct);
|
||||
$data['appointment_slot'] = $bookingProduct->appointment_slot;
|
||||
}
|
||||
|
||||
if ($bookingProduct->type == 'event') {
|
||||
$bookingSlotHelper = app('\Webkul\BookingProduct\Helpers\EventTicket');
|
||||
|
||||
$data['tickets'] = $bookingSlotHelper->getTickets($bookingProduct);
|
||||
$data['event_date'] = $bookingSlotHelper->getEventDate($bookingProduct);
|
||||
}
|
||||
|
||||
if ($bookingProduct->type == 'rental') {
|
||||
$data['renting_type'] = $bookingProduct->rental_slot->renting_type;
|
||||
}
|
||||
|
||||
if ($bookingProduct->type == 'table') {
|
||||
$bookingSlotHelper = app('\Webkul\BookingProduct\Helpers\TableSlot');
|
||||
|
||||
$data['today_slots_html'] = $bookingSlotHelper->getTodaySlotsHtml($bookingProduct);
|
||||
$data['week_slot_durations'] = $bookingSlotHelper->getWeekSlotDurations($bookingProduct);
|
||||
$data['table_slot'] = $bookingProduct->table_slot;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -581,12 +581,12 @@ class CartRule
|
|||
->where('cart_rule_channels.channel_id', $channelId)
|
||||
->where(function ($query1) {
|
||||
/** @var Builder $query1 */
|
||||
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))
|
||||
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d H:m:s'))
|
||||
->orWhereNull('cart_rules.starts_from');
|
||||
})
|
||||
->where(function ($query2) {
|
||||
/** @var Builder $query2 */
|
||||
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))
|
||||
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d H:m:s'))
|
||||
->orWhereNull('cart_rules.ends_till');
|
||||
})
|
||||
->with([
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use Webkul\Customer\Repositories\CustomerAddressRepository;
|
|||
|
||||
class Cart
|
||||
{
|
||||
|
||||
/**
|
||||
* CartRepository instance
|
||||
*
|
||||
|
|
@ -1290,6 +1289,25 @@ class Cart
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether cart has product.
|
||||
*
|
||||
* @param \Webkul\Product\Models\Product $product
|
||||
* @return bool
|
||||
*/
|
||||
public function hasProduct($product): bool
|
||||
{
|
||||
$cart = \Cart::getCart();
|
||||
|
||||
if (! $cart) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$count = $cart->all_items()->where('product_id', $product->id)->count();
|
||||
|
||||
return $count > 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check minimum order.
|
||||
*
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"/js/shop.js": "/js/shop.js?id=fd3e9e2c897df46dd84c",
|
||||
"/css/shop.css": "/css/shop.css?id=d080a007e2aec5d519b3"
|
||||
"/js/shop.js": "/js/shop.js?id=83c93b077da401f7b709",
|
||||
"/css/shop.css": "/css/shop.css?id=6f4a4f8fad1b25e05e33"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<template>
|
||||
<transition name="slide">
|
||||
<div class="slider-content" v-if="images.length > 0">
|
||||
|
||||
<ul class="slider-images">
|
||||
<li v-for="(image, index) in images" :key="index" v-bind:class="{'show': index==currentIndex}">
|
||||
<a :href="image.slider_path">
|
||||
|
|
@ -19,10 +18,29 @@
|
|||
</transition>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.slider-control {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.slide-enter-active {
|
||||
transition: all 0.2s cubic-bezier(0.55, 0.085, 0.68, 0.53);
|
||||
}
|
||||
|
||||
.slide-leave-active {
|
||||
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
|
||||
.slide-enter, .slide-leave-to {
|
||||
-webkit-transform: scaleY(0) translateZ(0);
|
||||
transform: scaleY(0) translateZ(0);
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
props:{
|
||||
props: {
|
||||
slides: {
|
||||
type: Array,
|
||||
required: true,
|
||||
|
|
@ -36,16 +54,11 @@ export default {
|
|||
},
|
||||
|
||||
data() {
|
||||
|
||||
return {
|
||||
images: [],
|
||||
|
||||
currentIndex: -1,
|
||||
|
||||
content: [],
|
||||
|
||||
current: false,
|
||||
|
||||
images_loaded: false,
|
||||
};
|
||||
},
|
||||
|
|
@ -55,7 +68,6 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
|
||||
getProps() {
|
||||
this.setProps();
|
||||
},
|
||||
|
|
@ -85,34 +97,18 @@ export default {
|
|||
changeIndexLeft: function() {
|
||||
if (this.currentIndex > 0) {
|
||||
this.currentIndex--;
|
||||
} else if(this.currentIndex == 0) {
|
||||
} else if (this.currentIndex == 0) {
|
||||
this.currentIndex = this.images.length-1;
|
||||
}
|
||||
},
|
||||
|
||||
changeIndexRight: function() {
|
||||
if(this.currentIndex < this.images.length-1) {
|
||||
if (this.currentIndex < this.images.length-1) {
|
||||
this.currentIndex++;
|
||||
} else if(this.currentIndex == this.images.length-1) {
|
||||
} else if (this.currentIndex == this.images.length-1) {
|
||||
this.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.slide-enter-active {
|
||||
transition: all 0.2s cubic-bezier(0.55, 0.085, 0.68, 0.53);
|
||||
}
|
||||
|
||||
.slide-leave-active {
|
||||
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
|
||||
.slide-enter, .slide-leave-to {
|
||||
-webkit-transform: scaleY(0) translateZ(0);
|
||||
transform: scaleY(0) translateZ(0);
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
</script>
|
||||
|
|
@ -1881,6 +1881,7 @@ section.product-detail {
|
|||
font-size: 24px;
|
||||
color: $font-dark;
|
||||
margin-bottom: 15px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
<div class="action">
|
||||
@foreach ($actions as $action)
|
||||
@php
|
||||
$toDisplay = (isset($action['condition']) && gettype($action['condition']) == 'object') ? $action['condition']() : true;
|
||||
$toDisplay = (isset($action['condition']) && gettype($action['condition']) == 'object') ? $action['condition']($record) : true;
|
||||
@endphp
|
||||
|
||||
@if ($toDisplay)
|
||||
|
|
|
|||
Loading…
Reference in New Issue