feat: refactor controllers and update department service usage for consistency
Some checks failed
tests / ci (pull_request) Has been cancelled
Some checks failed
tests / ci (pull_request) Has been cancelled
This commit is contained in:
parent
5901f8e649
commit
e6f272bb59
@ -15,7 +15,9 @@
|
|||||||
|
|
||||||
class FeedbackController extends Controller
|
class FeedbackController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct(private readonly FeedbackService $service) {}
|
public function __construct(
|
||||||
|
private readonly FeedbackService $service,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function index(PaginatedRequest $request): Response
|
public function index(PaginatedRequest $request): Response
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
use App\Http\Requests\PaginatedRequest;
|
use App\Http\Requests\PaginatedRequest;
|
||||||
use App\Models\Course;
|
use App\Models\Course;
|
||||||
use App\Services\Admin\Manage\CourseService;
|
use App\Services\Admin\Manage\CourseService;
|
||||||
use App\Services\Admin\Users\DepartmentService;
|
use App\Services\Admin\Master\DepartmentService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
|
|||||||
@ -49,8 +49,6 @@ public function destroy(Material $material): RedirectResponse
|
|||||||
{
|
{
|
||||||
$this->service->delete($material);
|
$this->service->delete($material);
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Materi berhasil dihapus.']);
|
return Inertia::flash('toast', ['type' => 'success', 'message' => 'Materi berhasil dihapus.'])->back();
|
||||||
|
|
||||||
return back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,8 +48,6 @@ public function destroy(Schedule $schedule): RedirectResponse
|
|||||||
{
|
{
|
||||||
$this->service->delete($schedule);
|
$this->service->delete($schedule);
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Jadwal berhasil dihapus.']);
|
return Inertia::flash('toast', ['type' => 'success', 'message' => 'Jadwal berhasil dihapus.'])->back();
|
||||||
|
|
||||||
return back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,8 +52,6 @@ public function destroy(TuitionInvoice $tuitionInvoice): RedirectResponse
|
|||||||
{
|
{
|
||||||
$this->service->delete($tuitionInvoice);
|
$this->service->delete($tuitionInvoice);
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Tagihan berhasil dihapus.']);
|
return Inertia::flash('toast', ['type' => 'success', 'message' => 'Tagihan berhasil dihapus.'])->back();
|
||||||
|
|
||||||
return back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
class AcademicTermController extends Controller
|
class AcademicTermController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly AcademicTermService $service
|
private readonly AcademicTermService $service,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function index(PaginatedRequest $request): Response
|
public function index(PaginatedRequest $request): Response
|
||||||
@ -33,18 +33,18 @@ public function store(AcademicTermRequest $request): RedirectResponse
|
|||||||
return to_route('admin.master.academic-terms.index');
|
return to_route('admin.master.academic-terms.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(AcademicTermRequest $request, AcademicTerm $AcademicTerm): RedirectResponse
|
public function update(AcademicTermRequest $request, AcademicTerm $academicTerm): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->update($AcademicTerm, $request->validated());
|
$this->service->update($academicTerm, $request->validated());
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Periode akademik berhasil diperbarui.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Periode akademik berhasil diperbarui.']);
|
||||||
|
|
||||||
return to_route('admin.master.academic-terms.index');
|
return to_route('admin.master.academic-terms.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(AcademicTerm $AcademicTerm): RedirectResponse
|
public function destroy(AcademicTerm $academicTerm): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->delete($AcademicTerm);
|
$this->service->delete($academicTerm);
|
||||||
|
|
||||||
return Inertia::flash('toast', ['type' => 'success', 'message' => 'Periode akademik berhasil dihapus.'])->back();
|
return Inertia::flash('toast', ['type' => 'success', 'message' => 'Periode akademik berhasil dihapus.'])->back();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
class DepartmentController extends Controller
|
class DepartmentController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly DepartmentService $service
|
private readonly DepartmentService $service,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function index(PaginatedRequest $request): Response
|
public function index(PaginatedRequest $request): Response
|
||||||
|
|||||||
@ -15,9 +15,6 @@
|
|||||||
|
|
||||||
class ProfileController extends Controller
|
class ProfileController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Show the user's profile settings page.
|
|
||||||
*/
|
|
||||||
public function edit(Request $request): Response
|
public function edit(Request $request): Response
|
||||||
{
|
{
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
@ -37,9 +34,6 @@ public function edit(Request $request): Response
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the user's profile information.
|
|
||||||
*/
|
|
||||||
public function update(ProfileUpdateRequest $request): RedirectResponse
|
public function update(ProfileUpdateRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
@ -61,9 +55,6 @@ public function update(ProfileUpdateRequest $request): RedirectResponse
|
|||||||
return to_route('admin.settings.profile.edit');
|
return to_route('admin.settings.profile.edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the user's profile.
|
|
||||||
*/
|
|
||||||
public function destroy(ProfileDeleteRequest $request): RedirectResponse
|
public function destroy(ProfileDeleteRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|||||||
@ -11,9 +11,6 @@
|
|||||||
|
|
||||||
class SecurityController extends Controller
|
class SecurityController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Show the user's security settings page.
|
|
||||||
*/
|
|
||||||
public function edit(): Response
|
public function edit(): Response
|
||||||
{
|
{
|
||||||
return Inertia::render('admin/settings/security', [
|
return Inertia::render('admin/settings/security', [
|
||||||
@ -21,17 +18,12 @@ public function edit(): Response
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the user's password.
|
|
||||||
*/
|
|
||||||
public function update(PasswordUpdateRequest $request): RedirectResponse
|
public function update(PasswordUpdateRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$request->user()->update([
|
$request->user()->update([
|
||||||
'password' => $request->password,
|
'password' => $request->password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Kata sandi berhasil diperbarui.']);
|
return Inertia::flash('toast', ['type' => 'success', 'message' => 'Kata sandi berhasil diperbarui.'])->back();
|
||||||
|
|
||||||
return back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
class AdministratorController extends Controller
|
class AdministratorController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected AdministratorService $service,
|
private readonly AdministratorService $service,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function index(Request $request): Response
|
public function index(Request $request): Response
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Admin\Users\LecturerRequest;
|
use App\Http\Requests\Admin\Users\LecturerRequest;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\Admin\Users\DepartmentService;
|
use App\Services\Admin\Master\DepartmentService;
|
||||||
use App\Services\Admin\Users\LecturerService;
|
use App\Services\Admin\Users\LecturerService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -15,8 +15,8 @@
|
|||||||
class LecturerController extends Controller
|
class LecturerController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected LecturerService $service,
|
private readonly LecturerService $service,
|
||||||
protected DepartmentService $departmentService,
|
private readonly DepartmentService $departmentService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function index(Request $request): Response
|
public function index(Request $request): Response
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Admin\Users\StudentRequest;
|
use App\Http\Requests\Admin\Users\StudentRequest;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\Admin\Users\DepartmentService;
|
use App\Services\Admin\Master\DepartmentService;
|
||||||
use App\Services\Admin\Users\LecturerService;
|
use App\Services\Admin\Users\LecturerService;
|
||||||
use App\Services\Admin\Users\StudentService;
|
use App\Services\Admin\Users\StudentService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
@ -16,9 +16,9 @@
|
|||||||
class StudentController extends Controller
|
class StudentController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected StudentService $service,
|
private readonly StudentService $service,
|
||||||
protected DepartmentService $departmentService,
|
private readonly DepartmentService $departmentService,
|
||||||
protected LecturerService $lecturerService,
|
private readonly LecturerService $lecturerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function index(Request $request): Response
|
public function index(Request $request): Response
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Services\Admin\Users;
|
|
||||||
|
|
||||||
use App\Models\Department;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
class DepartmentService
|
|
||||||
{
|
|
||||||
public function getAll(): Collection
|
|
||||||
{
|
|
||||||
return Department::select(['id', 'name'])->get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
155
docs/code-style.md
Normal file
155
docs/code-style.md
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
# Panduan Gaya Kode
|
||||||
|
|
||||||
|
Dokumen ini mencatat konvensi penulisan kode di proyek ini, supaya kontributor
|
||||||
|
(termasuk AI assistant) mengikuti pola yang sama dan tidak menulis ulang
|
||||||
|
solusi yang sudah ada dengan cara berbeda-beda di tiap file.
|
||||||
|
|
||||||
|
Setiap bagian punya status:
|
||||||
|
|
||||||
|
- ✅ **Selesai** — sudah diterapkan di seluruh kode yang relevan.
|
||||||
|
- 🚧 **Sebagian** — sudah ada polanya, tapi belum diterapkan di semua tempat.
|
||||||
|
- 📝 **Rencana** — baru berupa kesepakatan, belum diterapkan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Enum ✅
|
||||||
|
|
||||||
|
**Aturan:** setiap backed enum (`enum X: string`) wajib pakai trait
|
||||||
|
`App\Enums\Concerns\HasValues`. Jangan pernah menulis
|
||||||
|
`array_values(X::cases())` atau `array_column(X::cases(), 'value')` secara
|
||||||
|
manual — pakai `X::values()` (atau `X::options()` kalau butuh label untuk
|
||||||
|
dropdown/select).
|
||||||
|
|
||||||
|
```php
|
||||||
|
// app/Enums/Concerns/HasValues.php
|
||||||
|
trait HasValues
|
||||||
|
{
|
||||||
|
public static function values(): array // ['male', 'female']
|
||||||
|
public static function options(): array // [{value: 'male', label: 'Laki-laki'}, ...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Struktur enum standar:
|
||||||
|
|
||||||
|
```php
|
||||||
|
enum Gender: string
|
||||||
|
{
|
||||||
|
use HasValues;
|
||||||
|
|
||||||
|
case Male = 'male';
|
||||||
|
case Female = 'female';
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::Male => 'Laki-laki',
|
||||||
|
self::Female => 'Perempuan',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sebelum → Sesudah**
|
||||||
|
|
||||||
|
```php
|
||||||
|
// ❌ Jangan
|
||||||
|
'gender' => ['required', 'string', Rule::in(array_values(Gender::cases()))],
|
||||||
|
'type' => ['required', 'string', Rule::in(array_column(FeedbackType::cases(), 'value'))],
|
||||||
|
|
||||||
|
// ✅ Pakai
|
||||||
|
'gender' => ['required', 'string', Rule::in(Gender::values())],
|
||||||
|
'type' => ['required', 'string', Rule::in(FeedbackType::values())],
|
||||||
|
```
|
||||||
|
|
||||||
|
Untuk data yang dikirim ke frontend (mis. isi `<Select>`), pakai `options()`
|
||||||
|
alih-alih membangun array `{value, label}` manual dengan `array_map`:
|
||||||
|
|
||||||
|
```php
|
||||||
|
// ❌ Jangan
|
||||||
|
'types' => array_map(fn (FeedbackType $type) => [
|
||||||
|
'value' => $type->value,
|
||||||
|
'label' => $type->label(),
|
||||||
|
], FeedbackType::cases()),
|
||||||
|
|
||||||
|
// ✅ Pakai
|
||||||
|
'types' => FeedbackType::options(),
|
||||||
|
```
|
||||||
|
|
||||||
|
Enum baru **wajib** langsung pakai `use HasValues;` sejak awal dibuat, tidak
|
||||||
|
perlu menunggu ada kebutuhan `values()`/`options()` baru ditambahkan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Migration ✅
|
||||||
|
|
||||||
|
**Aturan:** kolom `enum()` di migration wajib pakai `EnumClass::values()`,
|
||||||
|
konsisten dengan aturan Enum di atas. Kolom `->default()` wajib pakai
|
||||||
|
`EnumClass::Case->value` (string), bukan objek case-nya langsung.
|
||||||
|
|
||||||
|
```php
|
||||||
|
// ❌ Jangan
|
||||||
|
$table->enum('status', array_values(StudentStatus::cases()))
|
||||||
|
->nullable()
|
||||||
|
->default(StudentStatus::Active); // objek enum, bukan string
|
||||||
|
|
||||||
|
// ✅ Pakai
|
||||||
|
$table->enum('status', StudentStatus::values())
|
||||||
|
->nullable()
|
||||||
|
->default(StudentStatus::Active->value);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Bahasa UI ✅
|
||||||
|
|
||||||
|
Seluruh teks yang tampil ke pengguna (label, judul halaman, pesan toast,
|
||||||
|
placeholder, pesan error) ditulis dalam **Bahasa Indonesia**. Istilah teknis
|
||||||
|
dan identifier kode tetap dalam bahasa aslinya (bahasa Inggris), tapi teks
|
||||||
|
yang dibaca pengguna — termasuk teks di halaman auth/settings bawaan
|
||||||
|
starter-kit yang aslinya berbahasa Inggris — harus diterjemahkan supaya
|
||||||
|
konsisten dengan sisa aplikasi.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Struktur modul Admin ✅
|
||||||
|
|
||||||
|
Semua fitur berada di bawah `/admin` — tidak ada lagi controller atau
|
||||||
|
halaman yang menggantung di top-level `App\Http\Controllers` /
|
||||||
|
`resources/js/pages/` di luar folder `admin/`. Setiap fitur admin baru
|
||||||
|
(CRUD) mengikuti struktur namespace yang sama, di salah satu dari lima grup:
|
||||||
|
|
||||||
|
| Grup | Namespace Controller/Request | Prefix route |
|
||||||
|
| ------------------ | --------------------------------------- | ------------------ |
|
||||||
|
| Master data | `Admin\Master` | `admin/master/*` |
|
||||||
|
| Data operasional | `Admin\Manage` | `admin/manage/*` |
|
||||||
|
| Manajemen pengguna | `Admin\Users` | `admin/users/*` |
|
||||||
|
| Pengaturan akun | `Admin\Settings` | `admin/settings/*` |
|
||||||
|
| Resource mandiri | `Admin` (langsung, tanpa sub-namespace) | `admin/<resource>` |
|
||||||
|
|
||||||
|
"Resource mandiri" dipakai untuk fitur yang tidak cocok masuk ke 4 grup di
|
||||||
|
atas — misalnya `Admin\FeedbackController` di `admin/feedback` (data
|
||||||
|
personal milik user yang sedang login, bukan data akademik yang dikelola
|
||||||
|
admin atas user lain).
|
||||||
|
|
||||||
|
Nama route mengikuti pola `admin.<grup>.<resource>.<action>` (atau
|
||||||
|
`admin.<resource>.<action>` untuk resource mandiri), dan file Wayfinder
|
||||||
|
hasil generate mengikuti struktur folder yang sama di
|
||||||
|
`resources/js/routes/admin/<grup>/<resource>/`.
|
||||||
|
|
||||||
|
Halaman CRUD frontend memakai pola: `PageHeader` (judul + tombol Tambah) →
|
||||||
|
`FormDialog` (Create/Edit) → `DataTable` + `columns.tsx` → `DeleteConfirmDialog`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Wayfinder ✅
|
||||||
|
|
||||||
|
Selalu jalankan generate dengan flag form variant, supaya `<Form
|
||||||
|
{...Controller.method.form()}>` tidak error saat runtime:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php artisan wayfinder:generate --with-form
|
||||||
|
```
|
||||||
|
|
||||||
|
`vite.config.ts` sudah diset `wayfinder({ formVariants: true })` sehingga
|
||||||
|
dev-server otomatis benar. Flag `--with-form` hanya wajib diingat kalau
|
||||||
|
generate manual lewat CLI.
|
||||||
Loading…
Reference in New Issue
Block a user