feat: standardize pagination method naming and signatures across services
Some checks failed
tests / ci (pull_request) Has been cancelled

This commit is contained in:
Yoga Pangestu 2026-08-25 21:30:16 +07:00
parent 6698211396
commit 03b1fcd7e7
24 changed files with 92 additions and 50 deletions

View File

@ -30,7 +30,7 @@ public function index(PaginatedRequest $request): Response
return Inertia::render('admin/manage/course-registrations/index', [
'registrations' => $this->service->paginated(...$request->validatedWithDefaults()),
'students' => $this->studentService->getAllForSelect(),
'academicTerms' => $this->academicTermService->getAll(),
'academicTerms' => $this->academicTermService->getAllForSelect(),
'courseClasses' => $this->courseClassService->getAllForSelect(),
'lecturers' => $this->lecturerService->getAllForSelect(),
]);

View File

@ -23,7 +23,7 @@ public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/announcements/index', [
'announcements' => $this->service->paginated(...$request->validatedWithDefaults()),
'departments' => $this->departmentService->getAll(),
'departments' => $this->departmentService->getAllForSelect(),
]);
}

View File

@ -27,9 +27,9 @@ public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/course-classes/index', [
'courseClasses' => $this->service->paginated(...$request->validatedWithDefaults()),
'courses' => $this->courseService->getAll(),
'courses' => $this->courseService->getAllForSelect(),
'lecturers' => $this->lecturerService->getAllForSelect(),
'academicTerms' => $this->academicTermService->getAll(),
'academicTerms' => $this->academicTermService->getAllForSelect(),
]);
}

View File

@ -23,7 +23,7 @@ public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/courses/index', [
'courses' => $this->service->paginated(...$request->validatedWithDefaults()),
'departments' => $this->departmentService->getAll(),
'departments' => $this->departmentService->getAllForSelect(),
]);
}

View File

@ -26,7 +26,7 @@ public function index(PaginatedRequest $request): Response
return Inertia::render('admin/manage/tuition-invoices/index', [
'invoices' => $this->service->paginated(...$request->validatedWithDefaults()),
'students' => $this->studentService->getAllForSelect(),
'academicTerms' => $this->academicTermService->getAll(),
'academicTerms' => $this->academicTermService->getAllForSelect(),
]);
}

View File

@ -4,10 +4,10 @@
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Users\AdministratorRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\User;
use App\Services\Admin\Users\AdministratorService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Spatie\Permission\Models\Role;
@ -18,11 +18,10 @@ public function __construct(
private readonly AdministratorService $service,
) {}
public function index(Request $request): Response
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/users/administrators/index', [
'administrators' => $this->service->getPaginated($request->only(['search', 'per_page'])),
'filters' => $request->only(['search', 'per_page']),
'administrators' => $this->service->paginated(...$request->validatedWithDefaults()),
]);
}

View File

@ -4,11 +4,11 @@
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Users\LecturerRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\User;
use App\Services\Admin\Master\DepartmentService;
use App\Services\Admin\Users\LecturerService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
@ -19,18 +19,17 @@ public function __construct(
private readonly DepartmentService $departmentService,
) {}
public function index(Request $request): Response
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/users/lecturers/index', [
'lecturers' => $this->service->getPaginated($request->only(['search', 'per_page'])),
'filters' => $request->only(['search', 'per_page']),
'lecturers' => $this->service->paginated(...$request->validatedWithDefaults()),
]);
}
public function create(): Response
{
return Inertia::render('admin/users/lecturers/create', [
'departments' => $this->departmentService->getAll(),
'departments' => $this->departmentService->getAllForSelect(),
]);
}
@ -49,7 +48,7 @@ public function edit(User $user): Response
return Inertia::render('admin/users/lecturers/edit', [
'user' => $user,
'departments' => $this->departmentService->getAll(),
'departments' => $this->departmentService->getAllForSelect(),
]);
}

View File

@ -4,12 +4,12 @@
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Users\StudentRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\User;
use App\Services\Admin\Master\DepartmentService;
use App\Services\Admin\Users\LecturerService;
use App\Services\Admin\Users\StudentService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
@ -21,18 +21,17 @@ public function __construct(
private readonly LecturerService $lecturerService,
) {}
public function index(Request $request): Response
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/users/students/index', [
'students' => $this->service->getPaginated($request->only(['search', 'per_page'])),
'filters' => $request->only(['search', 'per_page']),
'students' => $this->service->paginated(...$request->validatedWithDefaults()),
]);
}
public function create(): Response
{
return Inertia::render('admin/users/students/create', [
'departments' => $this->departmentService->getAll(),
'departments' => $this->departmentService->getAllForSelect(),
'lecturers' => $this->lecturerService->getAllForSelect(),
]);
}
@ -52,7 +51,7 @@ public function edit(User $user): Response
return Inertia::render('admin/users/students/edit', [
'user' => $user,
'departments' => $this->departmentService->getAll(),
'departments' => $this->departmentService->getAllForSelect(),
'lecturers' => $this->lecturerService->getAllForSelect(),
]);
}

View File

@ -40,7 +40,7 @@ public function __construct()
$this->sanitizer = new HtmlSanitizer($config);
}
public function paginated(User $user, int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(User $user, int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return Feedback::query()
->where('user_id', $user->id)

View File

@ -8,7 +8,7 @@
class AssignmentService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return Assignment::query()
->select(['id', 'course_class_id', 'title', 'description', 'deadline'])

View File

@ -9,7 +9,7 @@
class CourseRegistrationService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return CourseRegistration::query()
->select(['id', 'student_id', 'academic_term_id', 'course_class_id', 'status', 'approved_by', 'created_at'])

View File

@ -8,7 +8,7 @@
class MaterialService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return Material::query()
->select(['id', 'course_class_id', 'title', 'description', 'meeting_number'])

View File

@ -7,7 +7,7 @@
class AnnouncementService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return Announcement::query()
->select(['id', 'title', 'content', 'department_id', 'enrollment_year', 'created_by', 'created_at'])

View File

@ -15,7 +15,7 @@ public function getAllForSelect(): Collection
->get();
}
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return CourseClass::query()
->select(['id', 'course_id', 'lecturer_id', 'academic_term_id', 'class_name', 'method'])

View File

@ -8,12 +8,12 @@
class CourseService
{
public function getAll(): Collection
public function getAllForSelect(): Collection
{
return Course::select(['id', 'code', 'name', 'department_id'])->get();
}
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return Course::query()
->select(['id', 'code', 'name', 'credits', 'department_id', 'semester_number'])

View File

@ -7,7 +7,7 @@
class TuitionInvoiceService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return TuitionInvoice::query()
->select(['id', 'student_id', 'academic_term_id', 'amount_due', 'due_date'])

View File

@ -7,7 +7,7 @@
class AcademicAdvisingLogService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return AcademicAdvisingLog::query()
->select(['id', 'student_id', 'lecturer_id', 'topic', 'notes', 'session_date', 'created_at'])

View File

@ -9,7 +9,7 @@
class LetterRequestService
{
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return LetterRequest::query()
->select(['id', 'student_id', 'letter_type', 'purpose', 'status', 'processed_by', 'submitted_at', 'completed_at'])

View File

@ -8,12 +8,12 @@
class AcademicTermService
{
public function getAll(array $filters = []): Collection
public function getAllForSelect(): Collection
{
return AcademicTerm::select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active'])->latest()->get();
}
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return AcademicTerm::query()
->select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active'])

View File

@ -8,12 +8,12 @@
class DepartmentService
{
public function getAll(): Collection
public function getAllForSelect(): Collection
{
return Department::select(['id', 'code', 'name'])->get();
}
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc', array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return Department::query()
->select(['id', 'code', 'name', 'degree_level'])

View File

@ -9,17 +9,17 @@
class AdministratorService
{
public function getPaginated(array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return User::with(['profile', 'roles'])
->whereHas('roles', fn ($q) => $q->whereIn('name', ['staff-admin', 'staff-keuangan']))
->when($filters['search'] ?? null, fn ($q, $search) => $q->where(function ($query) use ($search) {
->when($search, fn ($q) => $q->where(function ($query) use ($search) {
$query->where('username', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhereHas('profile', fn ($q) => $q->where('full_name', 'like', "%{$search}%"));
}))
->latest()
->paginate($filters['per_page'] ?? 25);
->orderBy($sort, $direction)
->paginate($perPage);
}
public function create(array $data): User

View File

@ -16,18 +16,18 @@ public function getAllForSelect(): Collection
return Lecturer::with('user.profile')->get();
}
public function getPaginated(array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return User::with(['profile', 'lecturer.department'])
->whereHas('roles', fn ($q) => $q->where('name', 'dosen'))
->when($filters['search'] ?? null, fn ($q, $search) => $q->where(function ($query) use ($search) {
->when($search, fn ($q) => $q->where(function ($query) use ($search) {
$query->where('username', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhereHas('profile', fn ($q) => $q->where('full_name', 'like', "%{$search}%"))
->orWhereHas('lecturer', fn ($q) => $q->where('lecturer_number', 'like', "%{$search}%"));
}))
->latest()
->paginate($filters['per_page'] ?? 25);
->orderBy($sort, $direction)
->paginate($perPage);
}
public function create(array $data): User

View File

@ -16,18 +16,18 @@ public function getAllForSelect(): Collection
return Student::with(['user.profile', 'department'])->get();
}
public function getPaginated(array $filters = []): LengthAwarePaginator
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
{
return User::with(['profile', 'student.department'])
->whereHas('roles', fn ($q) => $q->where('name', 'mahasiswa'))
->when($filters['search'] ?? null, fn ($q, $search) => $q->where(function ($query) use ($search) {
->when($search, fn ($q) => $q->where(function ($query) use ($search) {
$query->where('username', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhereHas('profile', fn ($q) => $q->where('full_name', 'like', "%{$search}%"))
->orWhereHas('student', fn ($q) => $q->where('student_number', 'like', "%{$search}%"));
}))
->latest()
->paginate($filters['per_page'] ?? 25);
->orderBy($sort, $direction)
->paginate($perPage);
}
public function create(array $data): User

View File

@ -163,7 +163,52 @@ ### 4.1 Sub-namespace di dalam `Admin\Manage`
---
## 5. Wayfinder ✅
## 5. Service ✅
**Method listing berpaginasi wajib bernama `paginated()`**, bukan
`getPaginated()` atau nama lain. Signature-nya seragam di seluruh Service
(kecuali ada parameter domain tambahan di depan, seperti `User $user` di
`FeedbackService`):
```php
public function paginated(int $perPage = 25, string $search = '', string $sort = 'created_at', string $direction = 'desc'): LengthAwarePaginator
```
Jangan tambahkan parameter `array $filters = []` kalau tidak benar-benar
dipakai di dalam method — `PaginatedRequest::validatedWithDefaults()` cuma
menghasilkan `perPage`/`search`/`sort`/`direction`, jadi parameter `$filters`
di banyak Service sebelumnya selalu kosong dan tidak pernah terisi oleh
controller manapun.
Controller yang memanggilnya selalu pakai `PaginatedRequest` + spread:
```php
'items' => $this->service->paginated(...$request->validatedWithDefaults()),
```
**Method yang mengembalikan daftar penuh tanpa paginasi** dibedakan sesuai
kegunaannya:
- **`getAllForSelect()`** — dipakai kalau hasilnya untuk mengisi dropdown
`<Select>` di form fitur *lain* (mis. `DepartmentService::getAllForSelect()`
dipakai di form Course/Lecturer/Student, bukan di halaman Department
sendiri).
- **Nama sesuai domain** — kalau daftar itu justru jadi listing utama
halaman itu sendiri (bukan sumber dropdown fitur lain) dan memang tidak
butuh paginasi, pakai nama yang menjelaskan isinya, mis.
`ScheduleService::all()` (listing halaman jadwal) atau
`AttendanceService::sessions()` (listing sesi presensi).
Jangan pernah menulis `getAll()` polos — nama itu ambigu antara dua kasus
di atas.
Urutan method standar dalam satu Service: `getAllForSelect()` (kalau ada) →
`paginated()``create()``update()``delete()` → helper `private` di
paling bawah.
---
## 6. Wayfinder ✅
Selalu jalankan generate dengan flag form variant, supaya `<Form
{...Controller.method.form()}>` tidak error saat runtime: