Some checks failed
tests / ci (pull_request) Has been cancelled
- Created sub-namespaces under Admin\Manage for Course, Academic, Announcement, Finance, and Service. - Added new FormRequest classes for handling validation in each sub-namespace. - Implemented Service classes for managing business logic related to each resource. - Updated routes to reflect the new sub-namespace structure. - Enhanced code organization and maintainability by grouping related functionalities.
178 lines
6.6 KiB
Markdown
178 lines
6.6 KiB
Markdown
# 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`.
|
|
|
|
### 4.1 Sub-namespace di dalam `Admin\Manage`
|
|
|
|
`Admin\Manage` sendiri dipecah lagi jadi 5 sub-namespace, mengikuti
|
|
pengelompokan yang sama seperti grup di `app-sidebar.tsx` (Kelas, Kelola,
|
|
Pengumuman, Keuangan, Layanan). **URL/nama route tidak berubah** (tetap flat
|
|
`admin/manage/*` / `admin.manage.*`) — hanya struktur folder PHP-nya
|
|
(Controller, Request, Service) yang mengikuti sub-namespace ini.
|
|
|
|
| Sub-namespace | Grup sidebar | Resource |
|
|
| --------------------------- | ------------ | -------------------------------------------------------------------------- |
|
|
| `Admin\Manage\Course` | Kelola | Course, CourseClass, ClassEnrollment |
|
|
| `Admin\Manage\Academic` | Kelas | CourseRegistration, Material, Assignment, Submission, Schedule, Attendance |
|
|
| `Admin\Manage\Announcement` | Pengumuman | Announcement |
|
|
| `Admin\Manage\Finance` | Keuangan | TuitionInvoice, TuitionPayment |
|
|
| `Admin\Manage\Service` | Layanan | LetterRequest, AcademicAdvisingLog |
|
|
|
|
Kalau menambah resource baru di salah satu grup ini, taruh Controller di
|
|
`app/Http/Controllers/Admin/Manage/<SubNamespace>/`, Request-nya di
|
|
`app/Http/Requests/Admin/Manage/<SubNamespace>/`, dan Service-nya di
|
|
`app/Services/Admin/Manage/<SubNamespace>/` — jangan taruh langsung di
|
|
`Admin\Manage` tanpa sub-namespace lagi.
|
|
|
|
---
|
|
|
|
## 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.
|