¨4.0.1¨

This commit is contained in:
¨NW¨
2023-12-03 14:07:47 +00:00
parent c08b36d1b6
commit f35052522d
1112 changed files with 43019 additions and 24987 deletions

View File

@@ -14,6 +14,7 @@ class FlashSaleTabs extends Tabs
*/
protected $buttonOffset = false;
public function make()
{
$this->group('flash_sale_information', trans('flashsale::flash_sales.tabs.group.flash_sale_information'))
@@ -22,6 +23,7 @@ class FlashSaleTabs extends Tabs
->add($this->settings());
}
private function products()
{
return tap(new Tab('products', trans('flashsale::flash_sales.tabs.products')), function (Tab $tab) {
@@ -39,6 +41,7 @@ class FlashSaleTabs extends Tabs
});
}
private function settings()
{
return tap(new Tab('settings', trans('flashsale::flash_sales.tabs.settings')), function (Tab $tab) {

View File

@@ -19,6 +19,7 @@ class CreateFlashSalesTable extends Migration
});
}
/**
* Reverse the migrations.
*

View File

@@ -24,6 +24,7 @@ class CreateFlashSaleTranslationsTable extends Migration
});
}
/**
* Reverse the migrations.
*

View File

@@ -27,6 +27,7 @@ class CreateFlashSaleProductsTable extends Migration
});
}
/**
* Reverse the migrations.
*

View File

@@ -24,6 +24,7 @@ class CreateFlashSaleProductOrdersTable extends Migration
});
}
/**
* Reverse the migrations.
*

View File

@@ -15,7 +15,6 @@ class FlashSaleDatabaseSeeder extends Seeder
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}

View File

@@ -18,14 +18,18 @@ class FlashSale extends Model
* @var self
*/
private static $active;
/**
* The attributes that are translatable.
*
* @var array
*/
public $translatedAttributes = ['campaign_name'];
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = ['translations'];
/**
* The attributes that are mass assignable.
*
@@ -33,46 +37,12 @@ class FlashSale extends Model
*/
protected $fillable = ['id'];
/**
* The attributes that are translatable.
*
* @var array
*/
public $translatedAttributes = ['campaign_name'];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted()
{
static::saved(function ($flashSale) {
if (! empty(request()->has('products'))) {
$flashSale->saveProducts(request('products'));
}
});
}
/**
* Get the active flash sale.
*
* @param int $id
* @return self
*/
public static function active()
{
if (is_callable(self::$active)) {
return call_user_func(self::$active);
}
return new self;
}
/**
* Set an active flash sale campaign.
*
* @param int $id
*
* @return void
*/
public static function activeCampaign($id)
@@ -84,16 +54,30 @@ class FlashSale extends Model
};
}
public static function contains(Product $product)
{
return self::active()->products->contains($product);
}
public static function pivot(Product $product)
/**
* Get the active flash sale.
*
* @param int $id
*
* @return self
*/
public static function active()
{
return self::active()->products->find($product)->pivot;
if (is_callable(self::$active)) {
return call_user_func(self::$active);
}
return new self;
}
public static function remainingQty(Product $product)
{
$flashSaleProduct = self::pivot($product);
@@ -101,13 +85,36 @@ class FlashSale extends Model
return $flashSaleProduct->qty - $flashSaleProduct->sold;
}
public function scopeWithEligibleProducts($query)
public static function pivot(Product $product)
{
$query->with(['products' => function ($query) {
$query->forCard()->wherePivot('end_date', '>', now());
}]);
return self::active()->products->find($product)->pivot;
}
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted()
{
static::saved(function ($flashSale) {
if (!empty(request()->has('products'))) {
$flashSale->saveProducts(request('products'));
}
});
}
public function saveProducts($products)
{
$this->products()->sync(
$this->buildProductPivots($products)
);
}
public function products()
{
return $this->belongsToMany(Product::class, 'flash_sale_products')
@@ -116,18 +123,27 @@ class FlashSale extends Model
->orderBy('position');
}
public function scopeWithEligibleProducts($query)
{
$query->with(['products' => function ($query) {
$query->forCard()->wherePivot('end_date', '<>', null);
}]);
}
public function getPriceAttribute($price)
{
return Money::inDefaultCurrency($price);
}
public function saveProducts($products)
public function table()
{
$this->products()->sync(
$this->buildProductPivots($products)
);
return new AdminTable($this->query());
}
private function buildProductPivots($products)
{
return collect($products)->values()->mapWithKeys(function ($attributes, $index) {
@@ -139,9 +155,4 @@ class FlashSale extends Model
]];
});
}
public function table()
{
return new AdminTable($this->query());
}
}

View File

@@ -38,19 +38,22 @@ class FlashSaleProduct extends Pivot
*/
protected $appends = ['sold'];
public function getSoldAttribute()
{
return $this->orders()->sum('qty');
}
public function getPriceAttribute($price)
{
return Money::inDefaultCurrency($price);
}
public function orders()
{
return $this->belongsToMany(Order::class, 'flash_sale_product_orders', 'flash_sale_product_id')
->withPivot('qty');
}
public function getPriceAttribute($price)
{
return Money::inDefaultCurrency($price);
}
}

View File

@@ -14,6 +14,7 @@ class SaveFlashSaleRequest extends Request
*/
protected $availableAttributes = 'flashsale::attributes';
/**
* Get the validation rules that apply to the request.
*

View File

@@ -2,15 +2,12 @@
namespace Modules\FlashSale\Providers;
use Modules\Support\Traits\AddsAsset;
use Illuminate\Support\ServiceProvider;
use Modules\Admin\Ui\Facades\TabManager;
use Modules\FlashSale\Admin\FlashSaleTabs;
class FlashSaleServiceProvider extends ServiceProvider
{
use AddsAsset;
/**
* Bootstrap the application services.
*
@@ -19,7 +16,5 @@ class FlashSaleServiceProvider extends ServiceProvider
public function boot()
{
TabManager::register('flash_sales', FlashSaleTabs::class);
$this->addAdminAssets('admin.flash_sales.(create|edit)', ['admin.media.js', 'admin.flashsale.js']);
}
}

View File

@@ -1,16 +1,16 @@
import FlashSaleProduct from './FlashSaleProduct';
import FlashSaleProduct from "./FlashSaleProduct";
export default class {
constructor() {
this.productCount = 0;
this.addFlashSaleProducts(FleetCart.data['flash_sale.products']);
this.addFlashSaleProducts(FleetCart.data["flash_sale.products"]);
if (this.productCount === 0) {
this.addProduct();
}
this.addFlashSaleProductsError(FleetCart.errors['flash_sale.products']);
this.addFlashSaleProductsError(FleetCart.errors["flash_sale.products"]);
this.attachEventListeners();
this.makeProductPanelsSortable();
@@ -23,9 +23,12 @@ export default class {
}
addProduct(attributes = {}) {
let productTemplate = new FlashSaleProduct({ productPanelNumber: this.productCount++, product: attributes });
let productTemplate = new FlashSaleProduct({
productPanelNumber: this.productCount++,
product: attributes,
});
$('#products-wrapper').append(productTemplate.render());
$("#products-wrapper").append(productTemplate.render());
window.admin.selectize();
}
@@ -34,31 +37,31 @@ export default class {
for (let key in errors) {
let parent = this.getInputFieldForKey(key).parent();
parent.addClass('has-error');
parent.addClass("has-error");
parent.append(`<span class="help-block">${errors[key][0]}</span>`);
}
}
getInputFieldForKey(key) {
let keyParts = key.split('.');
let keyParts = key.split(".");
// Replace all "_" to "-".
keyParts = keyParts.map(k => {
return k.split('_').join('-');
keyParts = keyParts.map((k) => {
return k.split("_").join("-");
});
return $(`#${keyParts.join('-')}`);
return $(`#${keyParts.join("-")}`);
}
attachEventListeners() {
$('.add-product').on('click', () => {
$(".add-product").on("click", () => {
this.addProduct();
});
}
makeProductPanelsSortable() {
Sortable.create(document.getElementById('products-wrapper'), {
handle: '.drag-icon',
Sortable.create(document.getElementById("products-wrapper"), {
handle: ".drag-handle",
animation: 150,
});
}

View File

@@ -7,7 +7,7 @@ return [
'quantity' => 'Quantity',
'campaign_name' => 'Campaign Name',
// validation
# validation
'products.*.product_id' => 'Product',
'products.*.end_date' => 'End Date',
'products.*.price' => 'Price',

View File

@@ -16,3 +16,9 @@
@endsection
@include('flashsale::admin.flash_sales.partials.shortcuts')
@push('globals')
@vite([
'Modules/FlashSale/Resources/assets/admin/js/main.js',
])
@endpush

View File

@@ -18,3 +18,9 @@
@endsection
@include('flashsale::admin.flash_sales.partials.shortcuts')
@push('globals')
@vite([
'Modules/FlashSale/Resources/assets/admin/js/main.js',
])
@endpush

View File

@@ -25,7 +25,7 @@
@endcomponent
@push('scripts')
<script>
<script type="module">
new DataTable('#flash_sales-table .table', {
columns: [
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },

View File

@@ -6,7 +6,7 @@
@endpush
@push('scripts')
<script>
<script type="module">
keypressAction([
{ key: 'b', route: "{{ route('admin.flash_sales.index') }}" }
]);

View File

@@ -1,7 +1,7 @@
<script type="text/html" id="flash-sale-product-template">
<div class="panel">
<div class="panel-header clearfix">
<span class="drag-icon pull-left">
<span class="drag-handle pull-left">
<i class="fa">&#xf142;</i>
<i class="fa">&#xf142;</i>
</span>
@@ -48,8 +48,10 @@
{{ trans('flashsale::attributes.end_date') }}<span class="m-l-5 text-red">*</span>
</label>
<input type="text"
<input
type="text"
name="products[<%- productPanelNumber %>][end_date]"
data-time
class="form-control datetime-picker"
id="products-<%- productPanelNumber %>-campaign-end"
value="<%- product.pivot.end_date %>"

View File

@@ -8,6 +8,12 @@ Route::get('flash-sales', [
'middleware' => 'can:admin.flash_sales.index',
]);
Route::get('flash-sales/index/table', [
'as' => 'admin.flash_sales.table',
'uses' => 'FlashSaleController@table',
'middleware' => 'can:admin.flash_sales.index',
]);
Route::get('flash-sales/create', [
'as' => 'admin.flash_sales.create',
'uses' => 'FlashSaleController@create',