added fast category edit ux feature

master
A1Gard 1 day ago
parent 89f80a50ce
commit d1ef32bb79

@ -34,6 +34,8 @@ class ProductController extends XController
['title' => "Detail", 'class' => 'btn-outline-light', 'icon' => 'ri-eye-line'],
'destroy' =>
['title' => "Remove", 'class' => 'btn-outline-danger delete-confirm', 'icon' => 'ri-close-line'],
'category' =>
['title' => "Edit category", 'class' => 'btn-outline-light edit-category-btn', 'icon' => 'ri-list-check-3'],
];
@ -211,4 +213,27 @@ class ProductController extends XController
}
/*restore**/
/**
* @param $id Product's id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application|\Illuminate\View\View
*/
public function categoryEdit($id)
{
$product = Product::find($id);
$cats = Category::all(['id', 'name', 'parent_id']);
return view('admin.products.category-edit', compact('product', 'cats'));
}
public function categorySave(Product $item, Request $request)
{
$item->categories()->sync($request->input('cat'));
logAdmin(__METHOD__, __CLASS__, $item->id);
if ($request->ajax()) {
return ['OK' => true, 'message' => __('Categories saved successfully')];
} else {
return redirect()->back()->with(['message' => __('Categories saved successfully')]);
}
}
}

@ -31,6 +31,7 @@ import './panel/sotable-controller.js';
import './panel/prototypes.js';
import './panel/panel-window-loader.js';
import './panel/responsive-control.js';
import './panel/fast-edit.js';
// import './panel/seo-analyzer.js';
// chartjs.defaults.defaultFontFamily = "Vazir";

@ -0,0 +1,59 @@
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('.edit-category-btn')?.forEach(function (el) {
el.setAttribute('href', '#edit-category');
el.addEventListener('click', function (e) {
e.preventDefault();
let id = this.closest('tr').querySelector('input.chkbox').getAttribute('value');
const url = document.querySelector('#category-edit-url').value + id;
document.querySelector('#iframe-modal iframe').setAttribute('src', url);
document.querySelector('#iframe-modal').style.display = 'block';
});
});
document.querySelector('#iframe-modal')?.addEventListener('click', function (e) {
if (e.target == this) {
this.style.display = 'none';
}
});
document.querySelector('#categories-save-btn')?.addEventListener('click', function (e) {
e.preventDefault();
const url = document.querySelector('#ajax-sync-form').getAttribute('action');
// Serialize the form data
const formData = new FormData();
const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked');
checkboxes.forEach(checkbox => {
formData.append('cat[]', checkbox.value);
});
// Optional: log serialized data for debugging
for (const [key, value] of formData.entries()) {
console.log(`${key}: ${value}`);
}
// Get the URL from the form's action attribute
// Make the AJAX POST request using Axios
axios.post(url, formData)
.then(response => {
// Handle success
if (response.data.OK == true){
$toast.success(response.data.message);
}else{
$toast.error(response.data.error);
}
})
.catch(error => {
// Handle error
$toast.error( error);
});
});
});

@ -474,3 +474,34 @@ a.btn,a.action-btn,a.circle-btn{
}
}
.nested-ul{
list-style: none;
ul{
list-style: none;
}
input[type='checkbox']{
margin: 0 1rem;
}
}
#iframe-modal{
background: #00000011;
backdrop-filter: blur(10px);
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 999;
padding-top: 5vh;
display: none;
iframe{
border: 0;
height: 90vh;
width: 100%;
border-radius: 1rem;
}
}

@ -30,6 +30,10 @@
padding: 1rem;
}
}
.alert{
margin-bottom: 1rem;
}
}
.table-list {

@ -0,0 +1,27 @@
@include('components.panel-header')
<div id="panel-preloader">
<div class="loader"></div>
</div>
<input type="hidden" id="panel-dir" @if(langIsRTL(config('app.locale'))) value="rtl" @else value="ltr" @endif>
<form action="{{route('admin.product.category-save',$product->slug)}}" method="post" id="ajax-sync-form">
@csrf
<div class="container pt-4" >
@include('components.err')
<h5>
{{__("Categories")}} [{{$product->name}}]
</h5>
<ul class="nested-ul">
{!!showCatNestedControl($cats,old('cat',isset($product)?$product->categories()->pluck('id')->toArray():[]))!!}
</ul>
</div>
<button class="action-btn circle-btn"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-custom-class="custom-tooltip"
data-bs-title="{{__("Save")}}"
id="categories-save-btn"
>
<i class="ri-save-2-line"></i>
</button>
</form>
@include('components.panel-footer')

@ -10,6 +10,12 @@
@section('filter')
{{-- Other filters --}}
<h2>
<input type="hidden" id="category-edit-url" value="{{route('admin.product.category-edit','')}}/">
<div id="iframe-modal">
<div class="container">
<iframe href="#"></iframe>
</div>
</div>
<i class="ri-book-3-line"></i>
{{__("Category")}}:
</h2>

@ -301,6 +301,9 @@ Route::prefix(config('app.panel.prefix'))->name('admin.')->group(
Route::get('restore/{item}', [\App\Http\Controllers\Admin\ProductController::class, 'restore'])->name('restore');
Route::post('bulk', [\App\Http\Controllers\Admin\ProductController::class, "bulk"])->name('bulk');
Route::get('trashed', [\App\Http\Controllers\Admin\ProductController::class, "trashed"])->name('trashed');
Route::get('category/edit/{id}', [\App\Http\Controllers\Admin\ProductController::class, 'categoryEdit'])->name('category-edit');
Route::post('category/save/{item}', [\App\Http\Controllers\Admin\ProductController::class, 'categorySave'])->name('category-save');
});
Route::prefix('props')->name('prop.')->group(
function () {

Loading…
Cancel
Save