# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Agent Penanggung Jawab

| Atribut | Detail |
|---|---|
| **Nama Agent** | Thomas (thomas-programmer) |
| **Peran** | Agent programmer utama yang bertanggung jawab atas project ini |
| **Cara Memanggil** | `@agent-thomas-programmer` |
| **Tanggal Mulai** | 2026-05-20 |

**Tanggung jawab Thomas di project ini:**
- Development fitur baru sesuai kebutuhan bisnis
- Debugging dan analisis root cause bug
- Code review dan refactoring kode yang sudah ada
- Implementasi fitur backend (CodeIgniter 3) maupun frontend (Vue.js)
- Menjaga kualitas, konsistensi, dan maintainability kodebase

---

## Project Overview

**Aplikasi Al-Hijrah** adalah sistem manajemen progres belajar Al-Quran untuk lembaga pendidikan (TPQ/pesantren). Aplikasi ini digunakan oleh tiga jenis pengguna: admin, guru, dan orang tua siswa.

Domain: `https://myquranalhijrah.my.id/`

## Architecture

Proyek ini terdiri dari dua lapisan utama:

### 1. Backend: REST API (CodeIgniter 3 + PHP)
Lokasi: `rest-belajar/`

Framework CodeIgniter 3 dengan library tambahan:
- **chriskacerguis/codeigniter-restserver** — semua controller API extend `BD_Controller` yang extend `REST_Controller`
- **IonAuth** — manajemen user dan autentikasi session-based
- **Firebase JWT** — token JWT untuk autentikasi API (expire 5 jam)
- **PhpSpreadsheet** (via library `excel`) — import/export Excel

**Alur autentikasi:**
1. Client POST ke `/api/auth/login` → mendapat JWT token
2. Token disimpan di `localStorage` sebagai `jwt`
3. Setiap request API berikutnya membawa header `Authorization: Bearer <token>`
4. `BD_Controller::auth()` memvalidasi JWT di setiap endpoint yang memerlukan autentikasi

**Catatan penting:** Saat ini hampir semua controller menonaktifkan `$this->auth()` (di-comment). Ini berarti endpoint belum terlindungi JWT secara aktif.

### 2. Frontend: Vue.js SPA (tanpa build tools)
Tiga aplikasi terpisah, masing-masing untuk peran berbeda:
- `admin/` — admin sekolah (kelola siswa, guru, ortu, kelas, konfigurasi)
- `guru/` — guru Al-Quran (input nilai harian, ujian semester, lihat progres)
- `ortu/` — orang tua (pantau progres dan raport anak)

Setiap aplikasi adalah SPA Vue.js 2 yang di-load via `httpVueLoader` (komponen `.vue` di-load langsung dari server tanpa bundler). Routing menggunakan `vue-router`. Komponen `.vue` ada di `<role>/assets/page/`.

File entry point untuk setiap aplikasi: `<role>/assets/page/main.js`  
`base_url` API didefinisikan di sini, saat ini: `https://myquranalhijrah.my.id/rest-belajar/`

**Catatan:** `guru/assets/page/main.js` ada di `.gitignore` — file ini tidak di-commit.

## Database

- **Nama DB:** `belajar_alquran`
- **Host:** `127.0.0.1`, user: `fakhri`, password: `1`
- Driver: `mysqli`
- Config: `rest-belajar/application/config/database.php`

**Tabel/view penting yang bisa disimpulkan dari model:**
- `m_siswa` — data siswa (kolom: `id`, `NISN`, `Nama`, `kelas_id`, `ortu_id`)
- `m_alquran` — referensi surat Al-Quran (kolom: `id`, `transliteration`, `surat_alquran`)
- `h_nilai` — header penilaian (kolom: `uniqid`, `tanggal_penilaian`, `siswa_id`, `guru_id`, `alquran_id`, `jenis_penilaian`, `jenis_ujian`, `kelas`, `semester`, `tahun_ajaran`, `jilid`, `halaman`, `catatan`)
- `v_penilaian` — view detail penilaian
- `v_siswa` — view siswa (join dengan kelas dan ortu)
- `v_guru` — view data guru
- Tabel IonAuth: `users`, `groups`, `users_groups`, dll.

**Konfigurasi aktif (tahun ajaran & semester)** disimpan di tabel konfigurasi dan dibaca via `Model_konfigurasi`. Nilai ini digunakan di controller `Nilai`, `Target`, dll.

## Tiga Jenis Penilaian

Sistem mengenal tiga jenis penilaian (`jenis_penilaian`):
- `tilawah` — membaca Al-Quran dengan jilid dan halaman
- `tahfidz` — hafalan surat Al-Quran
- `santun` — penilaian akhlak/perilaku (disimpan per item dengan `nilai_huruf`)

Dan dua jenis ujian (`jenis_ujian`):
- `harian` — penilaian rutin harian
- `ujian_semester` — ujian akhir semester (masuk ke raport)

## Konvensi Penting

### Controller REST
- Semua controller extend `BD_Controller extends REST_Controller`
- Method diberi suffix HTTP verb: `index_get()`, `index_post()`, `index_put()`, `index_delete()`
- Method dengan path tambahan: `naik_kelas_put()`, `by_ortu_get($id)`, `detail_get($id)`
- ID record menggunakan `uniqid()` PHP (bukan auto-increment integer), kecuali tabel IonAuth

### Model
- Model spesifik per entitas: `Model_siswa`, `Model_nilai`, `Model_kelas`, dll.
- Ada `M_core` sebagai model generik (get_where, get_all, edit_data, delete_data, insert_data)
- Query banyak yang menggunakan **MySQL View** (`v_siswa`, `v_penilaian`, `v_guru`) — perubahan struktur harus mempertimbangkan view ini

### Frontend Vue
- Komponen diorganisir per role: `assets/page/admin/`, `assets/page/guru/`, `assets/page/ortu/`
- Token JWT dan `id_user` disimpan di `localStorage`
- `id_user === '1'` = admin (hardcoded di router guard)
- Axios config dengan Bearer token ada di computed property `config_axios` di instance Vue utama
- Guru group ID = `2` di IonAuth

## File SQL

Ada beberapa snapshot database di root:
- `database alhijrah.sql` — versi lama
- `belajar_alquran_2025-12-12.sql` — snapshot terbaru

Gunakan file terbaru untuk setup lokal.

## Setup Lokal

Tidak ada package manager (npm/composer tidak digunakan secara lokal — semua dependency sudah ter-commit atau di-load via CDN). Untuk menjalankan:

1. Jalankan web server (Apache/Nginx) yang mengarah ke root project
2. Import SQL terbaru ke MySQL: `belajar_alquran_2025-12-12.sql`
3. Sesuaikan kredensial DB di `rest-belajar/application/config/database.php` jika perlu
4. Akses `admin/`, `guru/`, atau `ortu/` via browser

Untuk pengembangan lokal, ubah `base_url` di `<role>/assets/page/main.js` dari domain production ke `localhost`.

---

## Struktur Folder

### Root project
```
aplikasi-alhijrah/
├── admin/           # Vue SPA — role admin
├── guru/            # Vue SPA — role guru
├── ortu/            # Vue SPA — role orang tua
├── rest-belajar/    # Backend CodeIgniter 3 REST API
├── *.sql            # Snapshot database (gunakan yang terbaru)
├── *.xlsx           # Sample data Excel (siswa, raport, tahfidz)
├── quran.json       # Referensi data surat Al-Quran
└── CLAUDE.md        # Dokumen ini
```

### `admin/` (SPA Admin)
```
admin/
├── index.html                       # Entry point (sidebar, navbar, scripts CDN)
├── img/                             # Aset gambar
└── assets/
    ├── page/                        # Halaman/komponen Vue
    │   ├── main.js                  # Router + Vue root instance
    │   ├── home.vue, login.vue, lupa_password.vue,
    │   │   verifikasi_kode.vue, ganti_password.vue,
    │   │   forbidden.vue, konfigurasi.vue
    │   ├── profile/profile.vue
    │   └── admin/
    │       ├── guru/list_guru.vue
    │       ├── siswa/list_siswa.vue, naik_kelas.vue
    │       ├── ortu/list_ortu.vue, detail_ortu.vue
    │       ├── progres/list_progres.vue, detail_progres.vue, riwayat_anak.vue
    │       └── rapor/list_rapor.vue, detail_rapor.vue   (BELUM ada route di main.js)
    └── plugins/                     # Library lokal: vue, vue-router, axios, moment,
                                     #  sweetalert2, qs, adminlte, accounting,
                                     #  terbilang, MaterialDesign-Webfont
```

### `guru/` (SPA Guru)
```
guru/
├── index.html
├── img/
└── assets/
    ├── page/
    │   ├── main.js                  # GITIGNORED — buat ulang jika fresh clone
    │   ├── home.vue, login.vue, lupa_password.vue,
    │   │   verifikasi_kode.vue, ganti_password.vue,
    │   │   forbidden.vue, konfigurasi.vue, siteplanlatar.vue
    │   └── guru/
    │       ├── profile/profile.vue
    │       ├── nilai/list_penilaian.vue, penilaian.vue,
    │       │       penilaian_per_kelas.vue, ujian_semester.vue
    │       ├── progres/list_progres.vue, detail_progres.vue, riwayat_anak.vue
    │       ├── rapor/list_rapor.vue, detail_rapor.vue
    │       ├── marketing/list_marketing.vue
    │       └── skor.vue             # Capaian target
    └── plugins/                     # Sama dengan admin
```

### `ortu/` (SPA Orang Tua)
```
ortu/
├── index.html
├── img/
└── assets/
    ├── page/
    │   ├── main.js
    │   ├── home.vue, login.vue, lupa_password.vue,
    │   │   verifikasi_kode.vue, ganti_password.vue
    │   ├── profile/profile.vue
    │   └── ortu/
    │       ├── profile/profile.vue
    │       ├── progres/list_progres.vue, detail_progres.vue, riwayat_anak.vue
    │       ├── rapor/list_rapor.vue, detail_rapor.vue
    │       └── skor.vue
    └── plugins/                     # Sama dengan admin/guru
```

### `rest-belajar/` (Backend CI3)
```
rest-belajar/
├── index.php                        # CI front controller
├── Booking.php                      # File standalone di root (kemungkinan legacy)
├── db/                              # Catatan DB
├── template/                        # Template (raport, dll.)
├── uploads/                         # File yang di-upload user
│   └── excel/                       # File import Excel
└── application/
    ├── config/
    │   ├── config.php               # Base config + 'thekey' (secret JWT)
    │   ├── database.php             # Kredensial DB
    │   ├── autoload.php             # Autoload: database, session, ion_auth, email
    │   ├── routes.php               # Hanya default + sample REST
    │   ├── rest.php                 # Konfigurasi REST_Controller
    │   ├── Midtrans.php             # (legacy/unused untuk Al-Hijrah)
    │   └── ...
    ├── core/
    │   └── BD_Controller.php        # Extends REST_Controller, method auth() untuk JWT
    ├── controllers/
    │   ├── Auth.php                 # Web (IonAuth) — login, logout, change_password, dll.
    │   ├── Konfigurasi.php          # CRUD konfigurasi semester/tahun ajaran
    │   ├── Nilai.php                # Penilaian harian + ujian semester + raport
    │   ├── Target.php               # Target tilawah/tahfidz per rombel
    │   ├── M_siswa.php, M_guru.php, M_ortu.php,
    │   ├── M_kelas.php, M_alquran.php, M_jilid.php,
    │   ├── M_parameter_nilai.php
    │   └── api/
    │       ├── Auth.php             # REST: login, register, forgotten_password,
    │       │                        #  verify_code, reset_password (JWT issuer)
    │       ├── Main.php             # users_get / users_delete (admin user mgmt)
    │       ├── Key.php              # API key management
    │       └── Auth_.php            # Backup/varian
    ├── models/
    │   ├── M_core.php               # Model generik (get_where, edit_data, dll.)
    │   ├── m_main.php               # Model utility tambahan
    │   ├── Model_siswa.php, Model_kelas.php, Model_alquran.php,
    │   ├── Model_jilid.php, Model_parameter_nilai.php,
    │   ├── Model_nilai.php          # Penilaian + raport + skor harian
    │   ├── Model_target.php         # Target tilawah/tahfidz
    │   └── Model_konfigurasi.php    # Pengaturan semester/tahun ajaran
    ├── libraries/
    │   ├── REST_Controller.php      # chriskacerguis REST server
    │   ├── JWT.php, BeforeValidException.php,
    │   │   ExpiredException.php, SignatureInvalidException.php
    │   ├── Excel.php                # Wrapper PhpSpreadsheet
    │   ├── Dompdf.php               # Wrapper Dompdf
    │   ├── Format.php, Curl.php
    │   ├── Phpmailer_lib.php        # PHPMailer (lupa password / verifikasi)
    │   ├── Terbilang_lib.php        # Angka -> kata
    │   └── Midtrans_lib.php         # (legacy)
    ├── helpers/
    │   ├── jwt_helper.php           # Helper JWT (varian implementasi)
    │   └── db_helper.php            # add_foreign_key, drop_foreign_key, add_trigger, dll.
    ├── third_party/
    │   ├── ion_auth/                # IonAuth (users, groups, dll.)
    │   ├── PhpSpreadsheet-1.12.0/   # Import/export Excel
    │   ├── PHPMailer/               # Kirim email
    │   ├── dompdf/                  # Generate PDF (raport)
    │   ├── php-terbilang/, psr/, Midtrans/
    └── views/                       # View IonAuth + halaman error
```

---

## Daftar Fitur per Role

### Admin (`admin/`)
Login dengan `id_user = 1` (hardcoded di router guard).

| Menu | Path | Komponen | Keterangan |
|---|---|---|---|
| Beranda | `/` | `home.vue` | Dashboard |
| Profile | `/profile` | `guru/profile/profile.vue` | (catatan: re-use komponen guru) |
| Data Siswa | `/list_siswa` | `admin/siswa/list_siswa.vue` | CRUD siswa + import Excel |
| Naik Kelas | `/naik_kelas` | (link di sidebar TAPI route tidak terdaftar di main.js) | Broken — perlu register route |
| Data Orang Tua | `/m_ortu` | `admin/ortu/list_ortu.vue` | CRUD ortu |
| Detail Ortu | `/detail_ortu/:id` | `admin/ortu/detail_ortu.vue` | Detail + daftar anak |
| Data Guru | `/m_guru` | `admin/guru/list_guru.vue` | CRUD guru Al-Quran |
| List Progres | `/list_progres` | `admin/progres/list_progres.vue` | Daftar progres semua siswa |
| Riwayat Anak | `/riwayat_anak/:id` | `admin/progres/riwayat_anak.vue` | Histori belajar |
| Detail Progres | `/detail_progres/:id` | `admin/progres/detail_progres.vue` | Detail penilaian |
| Konfigurasi | `/konfigurasi` | `konfigurasi.vue` | Set semester aktif & tahun ajaran |

**Catatan:** `admin/page/admin/rapor/*.vue` ada filenya tapi belum di-register di router.

### Guru (`guru/`)
Login dengan `id_user = 1` ATAU `id_user = 2` (router guard guru memperbolehkan keduanya). Group IonAuth = 2.

| Menu | Path | Komponen | Keterangan |
|---|---|---|---|
| Beranda | `/` | `home.vue` | Dashboard |
| Profile | `/profile` | `guru/profile/profile.vue` | |
| Assesment | `/list_penilaian` | `guru/nilai/list_penilaian.vue` | Pilih siswa untuk dinilai |
| Penilaian | `/penilaian/:jenis/:id` | `guru/nilai/penilaian.vue` | Input penilaian harian (tilawah/tahfidz/santun) |
| Ujian Semester | `/ujian_semester` | `guru/nilai/ujian_semester.vue` | Input nilai ujian semester |
| Penilaian Santun | `/penilaian_santun/:id` | `guru/nilai/penilaian_santun.vue` | (komponen referensi route belum dipastikan ada di disk dengan nama tsb — `penilaian_per_kelas.vue` ada) |
| Rapor | `/rapor/:id` | `guru/rapor/list_rapor.vue` | List rapor per siswa |
| Detail Rapor | `/detail_rapor/:id/:tahun_ajaran/:semester` | `guru/rapor/detail_rapor.vue` | Detail rapor per semester |
| Progres | `/list_progres` | `guru/progres/list_progres.vue` | |
| Riwayat Anak | `/riwayat_anak/:id` | `guru/progres/riwayat_anak.vue` | |
| Detail Progres | `/detail_progres/:id` | `guru/progres/detail_progres.vue` | |
| Capaian Target | `/skor` | `guru/skor.vue` | Papan skor target tilawah/tahfidz |

### Orang Tua (`ortu/`)
Login dengan `id_user = 1` (router guard ortu memakai check `== '1'`, ada inkonsistensi vs IonAuth role yang seharusnya bukan admin).

| Menu | Path | Komponen | Keterangan |
|---|---|---|---|
| Beranda | `/` | `home.vue` | Dashboard |
| Profile | `/profile` | `ortu/profile/profile.vue` | |
| Capaian Target | `/skor` | `ortu/skor.vue` | (menu aktif di sidebar) |
| Rapor | `/rapor/:id` | `ortu/rapor/list_rapor.vue` | (di-comment di sidebar tapi route hidup) |
| Detail Rapor | `/detail_rapor/:id/:tahun_ajaran/:semester` | `ortu/rapor/detail_rapor.vue` | |
| Progres | `/list_progres` | `ortu/progres/list_progres.vue` | (di-comment di sidebar tapi route hidup) |
| Riwayat Anak | `/riwayat_anak/:id` | `ortu/progres/riwayat_anak.vue` | |
| Detail Progres | `/detail_progres/:id` | `ortu/progres/detail_progres.vue` | |

**Catatan inkonsistensi pada ortu/main.js:**
- Route `list_penilaian`, `penilaian`, `penilaian_santun` mereferensikan folder `assets/page/ortu/nilai/` yang TIDAK ADA di disk → BROKEN bila diakses.
- Route guard memakai `id_user == '1'` (sama dengan admin) — perlu re-check apakah memang sesuai desain.

---

## API Endpoints

Base URL production: `https://myquranalhijrah.my.id/rest-belajar/`  
Pola URL CI3: `<base>/<Controller>/<method>` atau `<base>/<Controller>` (default `index_<verb>`).  
Controller di subfolder `api/` diakses dengan prefix `api/`.

### Autentikasi — `api/Auth`

| Method | Endpoint | Fungsi |
|---|---|---|
| POST | `api/auth/login` | Login dengan username/password → return JWT, id_user, nama_user |
| POST | `api/auth/register` | Registrasi user baru (via IonAuth) |
| POST | `api/auth/forgotten_password` | Trigger lupa password (kirim kode email) |
| POST | `api/auth/verify_code` | Verifikasi kode reset |
| POST | `api/auth/reset_password` | Set password baru |

JWT payload: `{id, username, iat, exp}`, exp = +5 jam. Secret: `config.thekey`.

### Penilaian — `Nilai`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `Nilai?siswa_id=&kelas=&tahun_ajaran=&semester=&page=&perPage=` | List penilaian siswa (paginated) |
| GET | `Nilai/detail?nilai_id=` | Detail satu header penilaian + item-itemnya |
| GET | `Nilai/skor_harian?rombel=&jenis_penilaian=` | Papan skor harian (default `tilawah`) |
| GET | `Nilai/raport?siswa_id=&page=&perPage=&max_item=` | List raport per semester |
| GET | `Nilai/raport_detail?siswa_id=&tahun_ajaran=&semester=` | Detail item raport |
| POST | `Nilai` | Insert penilaian harian (header + detail) |
| POST | `Nilai/semester` | Insert nilai ujian semester (per-item header) |
| DELETE | `Nilai/{nilai_id}` | Hapus penilaian |

### Master Data Siswa — `M_siswa`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `M_siswa` | List semua siswa (view `v_siswa`) |
| GET | `M_siswa/count` | Hitung total siswa |
| GET | `M_siswa/detail/{id}` | Detail satu siswa |
| GET | `M_siswa/by_ortu/{id_ortu}` | Daftar siswa per ortu |
| GET | `M_siswa/search?q=` | Cari siswa |
| POST | `M_siswa` | Tambah siswa |
| PUT | `M_siswa` | Update siswa |
| PUT | `M_siswa/naik-kelas` | Naik kelas batch (URL-dash di-translate ke `naik_kelas_put`) |
| DELETE | `M_siswa/{id}` | Hapus siswa |
| POST | `M_siswa/import` | Import Excel siswa |

### Master Data Guru — `M_guru`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `M_guru` | List guru |
| GET | `M_guru/count` | Hitung guru |
| POST | `M_guru` | Tambah guru (sekaligus user IonAuth) |
| PUT | `M_guru` | Update guru |
| POST | `M_guru/change_password` | Ganti password |
| POST | `M_guru/ubah_status_user` | Aktifkan/nonaktifkan |

### Master Data Ortu — `M_ortu`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `M_ortu` | List ortu |
| GET | `M_ortu/count` | Hitung ortu |
| GET | `M_ortu/detail/{id}` | Detail ortu + anak-anaknya |
| POST | `M_ortu` | Tambah ortu (+ user IonAuth) |
| PUT | `M_ortu` | Update ortu |
| POST | `M_ortu/change_password` | Ganti password |
| POST | `M_ortu/ubah_status_user` | Aktifkan/nonaktifkan |

### Master Kelas — `M_kelas`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `M_kelas` | List kelas |
| GET | `M_kelas/count` | Hitung kelas |
| GET | `M_kelas/search?q=` | Cari kelas |
| POST | `M_kelas` | Tambah kelas |
| PUT | `M_kelas/{id}` | Update kelas |
| DELETE | `M_kelas/{id}` | Hapus kelas |
| POST | `M_kelas/import` | Import Excel kelas |

### Referensi — `M_alquran`, `M_jilid`, `M_parameter_nilai`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `M_alquran` | List surat Al-Quran |
| GET | `M_alquran/pilih` | Dropdown surat |
| GET | `M_jilid` | List jilid |
| GET | `M_jilid/pilih` | Dropdown jilid |
| GET | `M_parameter_nilai` | List parameter penilaian (rubrik) |
| GET | `M_parameter_nilai/pilih/{rombel}/{jenis_penilaian}` | Rubrik per rombel & jenis |

### Target — `Target`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `Target` | List target |
| GET | `Target/pilih?rombel=&jenis_penilaian=` | Target per rombel + jenis (default `tilawah`) |

### Konfigurasi — `Konfigurasi`

| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `Konfigurasi` | Ambil semua konfigurasi (semester, tahun ajaran, dll.) |
| POST | `Konfigurasi` | Simpan konfigurasi baru |
| PUT | `Konfigurasi` | Update konfigurasi |

### Web Auth (legacy non-REST) — `Auth`
Controller `application/controllers/Auth.php` (CI standar, bukan REST). Menyediakan halaman web IonAuth: `index`, `login`, `logout`, `change_password`, `forgot_password`, `reset_password/{code}`, `activate/{id}/{code}`, `deactivate/{id}`, `create_user`, `edit_user/{id}`, `create_group`, `edit_group/{id}`. SPA tidak memakai ini secara langsung — gunakan `api/auth/*`.

---

## Library Frontend (CDN + Lokal)

Semua SPA me-load library yang sama via `index.html`:

| Library | Sumber | Fungsi |
|---|---|---|
| Vue 2 | `assets/plugins/vue/vue.js` | Framework |
| vue-router | `assets/plugins/vue/vue-router.js` | Routing |
| httpVueLoader | `assets/plugins/vue/httpVueLoader.min.js` | Load `.vue` tanpa bundler |
| axios | `assets/plugins/axios/axios.min.js` | HTTP client |
| moment | `assets/plugins/moment/moment-with-locales.min.js` | Format tanggal |
| qs | `assets/plugins/qs/qs.min.js` | Query string serializer |
| sweetalert2 | `assets/plugins/sweetalert2/sweetalert2.all.js` | Modal/alert |
| AdminLTE 3 | `assets/plugins/adminlte/*` | UI template |
| Bootstrap 4 | adminlte/plugins/bootstrap | CSS framework |
| jQuery | adminlte/plugins/jquery | Dep AdminLTE |
| BootstrapVue | CDN `unpkg.com/bootstrap-vue@latest` | Komponen `b-*` |
| vue-select | CDN `unpkg.com/vue-select@latest` | Dropdown |
| vee-validate | CDN `unpkg.com/vee-validate@2.2.15` | Validasi form |
| lodash | CDN `cdnjs.cloudflare.com/.../4.17.11` | Utility |
| accounting, terbilang | local | Format angka & angka→kata |
| MaterialDesign-Webfont | local | Ikon |

**Tidak ada Vuex** — state management via `localStorage` (jwt, id_user, nama_user) + props/event antar komponen.

---

## Inkonsistensi & Catatan Penting yang Ditemukan

1. **`admin/main.js`** tidak meng-register route `/naik_kelas` padahal sidebar `index.html` menautinya → broken link.
2. **`admin/main.js`** tidak meng-register route untuk `admin/rapor/list_rapor.vue` & `detail_rapor.vue` — file komponennya ada, tapi tidak ada path.
3. **`admin/main.js`** path `profile` mengarah ke `assets/page/guru/profile/profile.vue` (re-use komponen guru), kemungkinan typo — komponen `admin/page/profile/profile.vue` ada tapi tidak dipakai.
4. **`ortu/main.js`** mereferensikan folder `assets/page/ortu/nilai/` yang TIDAK ADA — route `/list_penilaian`, `/penilaian/...`, `/penilaian_santun/...` BROKEN bila dipanggil.
5. **`ortu/main.js`** router guard memakai `id_user == '1'` (sama dengan admin) — perlu konfirmasi: seharusnya ortu punya group ID berbeda.
6. **`guru/assets/page/main.js` ada di `.gitignore`** — jangan paksa commit, tapi pastikan ada salinan referensi.
7. Hampir semua controller men-disable `$this->auth()` (di-comment di constructor) → endpoint API tidak terlindungi JWT secara aktif. Hanya issuer (`api/Auth/login_post`) yang mengeluarkan token.
8. `BD_Controller::auth()` memakai algoritma `HS256` dan secret dari `config.thekey`.
9. **Controller `M_parameter_nilai`, `M_alquran`, `M_jilid`, `M_kelas`, `Konfigurasi`, `Target`** tidak extend `BD_Controller` (atau `REST_Controller` langsung) — perlu cek file: kelas dideklarasi tanpa `extends` di grep, tetapi tetap di-route oleh CI karena ada method `index_<verb>`. Verifikasi sebelum modifikasi.
10. File `rest-belajar/Booking.php` di root (di luar `application/`) — kemungkinan template lama; tidak ter-route oleh CI.

---

## Pola Konvensi Penting (untuk diingat saat coding)

- **Memanggil API dari Vue:** selalu pakai `base_url + "Nama_controller/method"`, header pakai `this.config_axios` (computed di Vue root yang otomatis lampirkan Bearer token dari localStorage).
- **CI3 URL dashes:** `$route['translate_uri_dashes'] = TRUE` → URL `naik-kelas` di-route ke method `naik_kelas_put`.
- **Konfigurasi semester/tahun ajaran** diambil di constructor controller, di-set sebagai `config_item` lalu dipakai dengan `$this->config->item('semester')` / `'tahun_ajaran'`.
- **ID record `uniqid("prefix", TRUE)`** dipakai untuk hampir semua tabel kustom (siswa, nilai, kelas, parameter, dll.). User IonAuth tetap auto-increment.
- **Timezone server** di-set ke `Asia/Jakarta` di setiap controller yang butuh tanggal (`Nilai`).
- **Penilaian harian vs ujian:** `Nilai::index_post` untuk harian (1 header + banyak detail), `Nilai::semester_post` untuk ujian (banyak header per `item_assessment`).
