feat(schedules): add 'select all N' across pages
- Add GetAllScheduleIdsAction + GetFilteredScheduleIdsTask - Add GET /dashboard/schedules/all-ids route returning filtered IDs - Add selectAllFiltered method to Index.vue - Button 'Выбрать все N' appears when total > per-page count
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Containers\Dashboard\Actions\Schedules;
|
||||||
|
|
||||||
|
use App\Containers\Dashboard\Tasks\Schedules\GetFilteredScheduleIdsTask;
|
||||||
|
|
||||||
|
class GetAllScheduleIdsAction
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly GetFilteredScheduleIdsTask $task,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function run(array $filters = []): array
|
||||||
|
{
|
||||||
|
return $this->task->run($filters);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Containers\Dashboard\Tasks\Schedules;
|
||||||
|
|
||||||
|
use App\Containers\Schedule\Models\Schedule;
|
||||||
|
|
||||||
|
class GetFilteredScheduleIdsTask
|
||||||
|
{
|
||||||
|
public function run(array $filters = []): array
|
||||||
|
{
|
||||||
|
$query = Schedule::query();
|
||||||
|
|
||||||
|
if (!empty($filters['educational_group_id'])) {
|
||||||
|
$query->where('educational_group_id', $filters['educational_group_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($filters['education_form_id'])) {
|
||||||
|
$query->whereHas('educationalGroup', function ($q) use ($filters) {
|
||||||
|
$q->where('education_form_id', $filters['education_form_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($filters['search'])) {
|
||||||
|
$query->whereHas('educationalGroup', function ($q) use ($filters) {
|
||||||
|
$q->where('title', 'like', '%' . $filters['search'] . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->pluck('id')->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ use App\Containers\Dashboard\Actions\Schedules\CreateScheduleAction;
|
|||||||
use App\Containers\Dashboard\Actions\Schedules\UpdateScheduleAction;
|
use App\Containers\Dashboard\Actions\Schedules\UpdateScheduleAction;
|
||||||
use App\Containers\Dashboard\Actions\Schedules\DeleteScheduleAction;
|
use App\Containers\Dashboard\Actions\Schedules\DeleteScheduleAction;
|
||||||
use App\Containers\Dashboard\Actions\Schedules\BulkDeleteSchedulesAction;
|
use App\Containers\Dashboard\Actions\Schedules\BulkDeleteSchedulesAction;
|
||||||
|
use App\Containers\Dashboard\Actions\Schedules\GetAllScheduleIdsAction;
|
||||||
use App\Containers\Dashboard\Actions\Schedules\ListSchedulesAction;
|
use App\Containers\Dashboard\Actions\Schedules\ListSchedulesAction;
|
||||||
use App\Containers\Dashboard\UI\WEB\Requests\StoreScheduleRequest;
|
use App\Containers\Dashboard\UI\WEB\Requests\StoreScheduleRequest;
|
||||||
use App\Containers\Dashboard\UI\WEB\Requests\UpdateScheduleRequest;
|
use App\Containers\Dashboard\UI\WEB\Requests\UpdateScheduleRequest;
|
||||||
@@ -25,6 +26,7 @@ class ScheduleController extends Controller
|
|||||||
private readonly UpdateScheduleAction $updateScheduleAction,
|
private readonly UpdateScheduleAction $updateScheduleAction,
|
||||||
private readonly DeleteScheduleAction $deleteScheduleAction,
|
private readonly DeleteScheduleAction $deleteScheduleAction,
|
||||||
private readonly BulkDeleteSchedulesAction $bulkDeleteSchedulesAction,
|
private readonly BulkDeleteSchedulesAction $bulkDeleteSchedulesAction,
|
||||||
|
private readonly GetAllScheduleIdsAction $getAllScheduleIdsAction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,4 +172,16 @@ class ScheduleController extends Controller
|
|||||||
->with('error', 'Ошибка при удалении: ' . $e->getMessage());
|
->with('error', 'Ошибка при удалении: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Все ID расписаний с учётом фильтров (для массового выделения)
|
||||||
|
*/
|
||||||
|
public function allIds(Request $request): \Illuminate\Http\JsonResponse
|
||||||
|
{
|
||||||
|
$filters = $request->only(['search', 'educational_group_id', 'education_form_id']);
|
||||||
|
|
||||||
|
$ids = $this->getAllScheduleIdsAction->run($filters);
|
||||||
|
|
||||||
|
return response()->json(['ids' => $ids, 'total' => count($ids)]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ Route::middleware(['access-check', 'dashboard.auth', 'dashboard.permission'])->g
|
|||||||
Route::get('/create', [ScheduleController::class, 'create'])->name('create');
|
Route::get('/create', [ScheduleController::class, 'create'])->name('create');
|
||||||
Route::post('/', [ScheduleController::class, 'store'])->name('store');
|
Route::post('/', [ScheduleController::class, 'store'])->name('store');
|
||||||
Route::delete('/bulk-destroy', [ScheduleController::class, 'bulkDestroy'])->name('bulk-destroy');
|
Route::delete('/bulk-destroy', [ScheduleController::class, 'bulkDestroy'])->name('bulk-destroy');
|
||||||
|
Route::get('/all-ids', [ScheduleController::class, 'allIds'])->name('all-ids');
|
||||||
Route::get('/{schedule}/edit', [ScheduleController::class, 'edit'])->name('edit');
|
Route::get('/{schedule}/edit', [ScheduleController::class, 'edit'])->name('edit');
|
||||||
Route::put('/{schedule}', [ScheduleController::class, 'update'])->name('update');
|
Route::put('/{schedule}', [ScheduleController::class, 'update'])->name('update');
|
||||||
Route::delete('/{schedule}', [ScheduleController::class, 'destroy'])->name('destroy');
|
Route::delete('/{schedule}', [ScheduleController::class, 'destroy'])->name('destroy');
|
||||||
|
|||||||
@@ -37,6 +37,11 @@
|
|||||||
class="text-xs text-muted-foreground-1 hover:text-primary transition-colors">
|
class="text-xs text-muted-foreground-1 hover:text-primary transition-colors">
|
||||||
Выбрать все на странице
|
Выбрать все на странице
|
||||||
</button>
|
</button>
|
||||||
|
<button v-if="schedules.total > schedules.data.length"
|
||||||
|
@click="selectAllFiltered" :disabled="bulkProcessing"
|
||||||
|
class="text-xs text-muted-foreground-1 hover:text-primary transition-colors disabled:opacity-50">
|
||||||
|
Выбрать все {{ schedules.total }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button @click="bulkDelete" :disabled="bulkProcessing"
|
<button @click="bulkDelete" :disabled="bulkProcessing"
|
||||||
@@ -405,6 +410,23 @@ export default {
|
|||||||
this.selectedSchedules = [...new Set([...this.selectedSchedules, ...this.schedules.data.map(s => s.id)])];
|
this.selectedSchedules = [...new Set([...this.selectedSchedules, ...this.schedules.data.map(s => s.id)])];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
selectAllFiltered() {
|
||||||
|
this.bulkProcessing = true;
|
||||||
|
fetch(route('dashboard.schedules.all-ids') + '?' + new URLSearchParams({
|
||||||
|
search: this.searchQuery,
|
||||||
|
educational_group_id: this.educationalGroupQuery,
|
||||||
|
education_form_id: this.educationFormQuery,
|
||||||
|
}).toString())
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
this.selectedSchedules = [...new Set([...this.selectedSchedules, ...data.ids])];
|
||||||
|
this.bulkProcessing = false;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.bulkProcessing = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
this.selectedSchedules = [];
|
this.selectedSchedules = [];
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user