# Panduan Pemasangan & Persediaan CMS Laravel

Projek ini adalah **Sistem Pengurusan Kandungan (CMS)** dibina menggunakan **Laravel 13**, **Tailwind CSS v4**, dan **TailAdmin** sebagai tema pentadbiran.

---

## Keperluan Sistem

| Keperluan | Versi Minimum |
|---|---|
| PHP | 8.3+ |
| Composer | 2.x |
| Node.js | 20+ |
| NPM | 10+ |
| MySQL | 8.0+ (atau MariaDB 10.6+) |
| Redis | 7+ (pilihan, untuk caching) |
| Extensions PHP | `bcmath`, `ctype`, `fileinfo`, `json`, `mbstring`, `openssl`, `pdo`, `pdo_mysql`, `redis`, `tokenmap`, `xml` |

---

## Langkah 1: Clone Projek

```bash
git clone <repository-url> cms-laravel
cd cms-laravel
```

---

## Langkah 2: Persediaan Persekitaran (.env)

Salin fail persekitaran dan sesuaikan:

```bash
cp .env.example .env
```

Edit `.env` dan tetapkan pangkalan data serta konfigurasi lain:

```env
APP_NAME="CMS Laravel"
APP_URL=http://localhost:8000

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cms_laravel_v1
DB_USERNAME=root
DB_PASSWORD=

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
```

### Konfigurasi Lain (Pilihan)

| Parameter | Penerangan |
|---|---|
| `SESSION_DRIVER` | Lalai `database`, boleh tukar ke `file`, `redis` |
| `QUEUE_CONNECTION` | Lalai `database`, boleh tukar ke `redis` |
| `CACHE_STORE` | Lalai `database`, boleh tukar ke `redis`, `file` |
| `MAIL_MAILER` | Lalai `log`, boleh tukar ke `smtp` untuk penghantaran emel sebenar |

---

## Langkah 3: Pasang Kebergantungan PHP (Composer)

```bash
composer install
```

Ini akan memasang pakej utama termasuk:

- `laravel/framework` ^13.0
- `spatie/laravel-permission` ^7.3 — pengurusan peranan & kebenaran
- `spatie/laravel-activitylog` ^5.0 — log aktiviti
- `barryvdh/laravel-elfinder` ^0.6.0 — pengurus fail
- `php-flasher/flasher-laravel` ^2.6 — pemberitahuan kilat
- `php-flasher/flasher-sweetalert-laravel` ^2.6 — dialog SweetAlert

---

## Langkah 4: Jana Kunci Aplikasi

```bash
php artisan key:generate
```

Hasilkan kunci aplikasi secara rawak dan tetapkan secara automatik dalam fail `.env`.

---

## Langkah 5: Persediaan Pangkalan Data

### 5.1 Cipta Pangkalan Data

Log masuk ke MySQL dan cipta pangkalan data:

```sql
CREATE DATABASE cms_laravel_v1 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

### 5.2 Jalankan Migrasi

```bash
php artisan migrate
```

Ini akan mencipta semua jadual yang diperlukan termasuk:

- jadual pengguna, peranan, kebenaran (dari Spatie)
- jadual sesi, cache, baris gilir (disimpan dalam pangkalan data)
- jadual log aktiviti
- jadual modul CMS yang lain

### 5.3 Isi Data Awal (Seeder)

```bash
php artisan db:seed
```

Seeder akan mencipta:

- Peranan lalai (Admin, Pengguna, dll.)
- Kebenaran dinamik berdasarkan model yang ada
- Pengguna admin lalai (jika ada dalam seeder)
- Konfigurasi awal sistem

---

## Langkah 6: Pasang & Bina Aset Frontend

Projek ini menggunakan **Vite** sebagai pembina aset.

### 6.1 Pasang Kebergantungan Node.js (Root Projek)

```bash
npm install
```

Pakej utama termasuk:

| Pakej | Kegunaan |
|---|---|
| `tailwindcss` ^4.0 | Rangka kerja CSS |
| `@tailwindcss/vite` ^4.0 | Pemalam Vite untuk Tailwind |
| `vite` ^8.0 | Pembina aset |
| `alpinejs` ^3.15 | Rangka kerja JS ringan |
| `apexcharts` / `chart.js` | Carta & graf |
| `grapesjs` ^0.23 | Pembina halaman seret & lepas |
| `filepond` ^4.32 | Pemuat naik fail |
| `sweetalert2` ^11 | Dialog pop-up |
| `@fortawesome/fontawesome-free` ^7 | Ikon |

### 6.2 Pasang & Bina Tema Admin (TailAdmin)

Tema pentadbiran terletak dalam direktori berasingan:

```bash
cd public/tailadmin
npm install
npm run build
cd ../../
```

### 6.3 Bina Aset Projek

```bash
npm run build
```

Untuk pembangunan (dengan pemantauan perubahan):

```bash
npm run dev
```

---

## Langkah 7: Persediaan Storage

Pastikan direktori `storage` boleh ditulis:

```bash
php artisan storage:link
```

Buat pautan simbolik daripada `public/storage` ke `storage/app/public`.

Tetapkan kebenaran (Linux/Mac):

```bash
chmod -R 775 storage bootstrap/cache
```

Jika web server berjalan sebagai user lain (contohnya `www-data`), tetapkan ownership supaya web server boleh menulis:

```bash
sudo chown -R nizarkhan:www-data /var/www/html/portal-v1/storage /var/www/html/portal-v1/bootstrap/cache
sudo chmod -R 775 /var/www/html/portal-v1/storage /var/www/html/portal-v1/bootstrap/cache
```

> **Nota:** Tukar `nizarkhan` kepada username project anda, dan `/var/www/html/portal-v1` kepada path sebenar project di server.
>
> Contoh hasil yang betul:
> ```bash
> drwxrwxr-x  2 nizarkhan www-data  4096 ... bootstrap/cache
> drwxrwxr-x  6 nizarkhan www-data  4096 ... storage
> ```

---

## Langkah 8: Jalankan Aplikasi

### Pelayan Pembangunan (Laravel)

```bash
php artisan serve
```

Akses di: http://localhost:8000

### Pelayan Pembangunan (Vite — untuk Hot Module Replacement)

Jalankan dalam terminal berasingan:

```bash
npm run dev
```

---

## Langkah 9: Deployment ke Production (HTTPS)

Bila dihost dengan HTTPS (contohnya di cPanel, Cloudflare, atau mana-mana hosting dengan SSL), pastikan konfigurasi berikut:

### 9.1 Tetapkan `.env` untuk Production

```env
APP_ENV=production
APP_DEBUG=false
APP_URL=https://domain-anda.com
```

Gantikan `https://domain-anda.com` dengan domain sebenar aplikasi.

### 9.2 Force HTTPS dalam Production

Dalam `app/Providers/AppServiceProvider.php`, kod berikut telah ditambah supaya Laravel sentiasa menghasilkan URL `https://` apabila `APP_ENV=production`:

```php
use Illuminate\Support\Facades\URL;

public function boot(): void
{
    if ($this->app->environment('production')) {
        URL::forceScheme('https');
    }

    // ...
}
```

Ini mengelakkan masalah **Mixed Content** di mana browser block aset `http://` dalam halaman `https://`.

### 9.3 Monaco Editor (Code Editor)

Monaco Editor diload secara relative path supaya tidak bergantung pada protokol URL:

```js
require.config({ paths: { vs: '/vendor/monaco-editor/min/vs' } });
```

File yang terlibat:
- `resources/views/backend/module/frontendSite/site/edit.blade.php`
- `resources/views/backend/module/frontendSite/site/create.blade.php`
- `resources/views/backend/module/frontendSite/page/edit.blade.php`
- `resources/views/backend/module/frontendSite/page/create.blade.php`
- `resources/views/backend/module/frontendSite/component/edit.blade.php`
- `resources/views/backend/module/frontendSite/component/create.blade.php`
- `resources/views/backend/module/dataDashboard/edit.blade.php`
- `resources/views/backend/module/dataDashboard/create.blade.php`
- `resources/views/backend/module/theme/theme-rule/form.blade.php`

### 9.4 Clear Cache Selepas Deploy

Setiap kali tukar `.env` atau upload kod baharu ke production, clear cache:

```bash
php artisan config:cache
php artisan view:clear
php artisan route:cache
php artisan optimize:clear
```

> **Nota:** Jangan biarkan `APP_DEBUG=true` dalam production kerana ia akan memaparkan maklumat sensitif bila berlakunya ralat.

---

## Langkah 10: Log Masuk Pentadbir (Selepas Seed)

| Medan | Nilai |
|---|---|
| URL | http://localhost:8000/admin |
| E-mel | (semak seeder `DatabaseSeeder.php`) |
| Kata Laluan | (semak seeder `DatabaseSeeder.php`) |

> **Nota:** Rujuk `database/seeders/` untuk butiran akaun lalai yang dibuat oleh seeder.

---

## Struktur Direktori Utama

```
├── app/
│   ├── Http/
│   │   ├── Controllers/     # Pengawal (Backend & Frontend)
│   │   └── Middleware/       # Middleware (CheckDynamicPermission, dll.)
│   ├── Models/
│   │   ├── Concerns/
│   │   │   └── HasDynamicPermissions.php  # Trait kebenaran dinamik
│   │   └── ...
│   └── Helpers/
│       └── DynamicPermissionHelper.php    # Pembantu format kebenaran
├── config/                   # Fail konfigurasi
├── database/
│   ├── migrations/           # Migrasi pangkalan data
│   └── seeders/              # Seeder data awal
├── public/
│   ├── tailadmin/            # Tema admin (TailAdmin)
│   └── vendor/               # Aset vendor (Select2, Monaco, dll.)
├── resources/
│   ├── css/                  # Stylesheet
│   ├── js/                   # JavaScript
│   └── views/                # Template Blade (backend + frontend)
├── routes/                   # Definis laluan
├── storage/                  # Log, cache, sesi, muat naik
└── tests/                    # Ujian PHPUnit
```

---

## Perintah Berguna

### Pengurusan Pangkalan Data

| Perintah | Penerangan |
|---|---|
| `php artisan migrate` | Jalankan migrasi belum dijalankan |
| `php artisan migrate:fresh` | Padam semua jadual dan migrasi semula |
| `php artisan migrate:refresh` | Rollback dan migrasi semula |
| `php artisan db:seed` | Isi data awal |
| `php artisan migrate:fresh --seed` | Padam, migrasi dan isi data sekaligus |

### Pembangunan

| Perintah | Penerangan |
|---|---|
| `php artisan serve` | Pelayan pembangunan Laravel |
| `npm run dev` | Vite dengan HMR (Hot Module Replacement) |
| `npm run build` | Bina aset untuk pengeluaran |
| `php artisan make:model ModelName -mf` | Cipta model dengan migrasi & factory |
| `php artisan make:controller NamaController` | Cipta pengawal baharu |

### Pengeluaran

| Perintah | Penerangan |
|---|---|
| `php artisan optimize` | Optimakan cache routing & config |
| `php artisan config:cache` | Cache konfigurasi |
| `php artisan route:cache` | Cache laluan |
| `php artisan view:cache` | Cache view Blade |

### Debug

| Perintah | Penerangan |
|---|---|
| `php artisan pail` | Monitor log masa nyata (Laravel Pail) |
| `php artisan tinker` | Interaktif shell untuk ujian |
| `composer pint` | Format kod secara automatik (Laravel Pint) |

---

## Penyelesaian Masalah Lazim

### 1. Ralat "Target class [controller] does not exist"

Pastikan ruang nama pengawal betul dalam fail laluan.

### 2. Ralat 500 selepas `composer install`

Jalankan semula:
```bash
php artisan optimize
php artisan key:generate
```

### 3. Isu Kebenaran Storage (Linux/Mac)

```bash
chmod -R 775 storage bootstrap/cache
```

### 4. "Vite manifest not found"

Pastikan `npm run build` telah dijalankan.

### 5. Ralat Pangkalan Data "Connection refused"

Pastikan perkhidmatan MySQL sedang berjalan dan butiran dalam `.env` adalah betul.

### 6. Sesi / Cache / Baris Gilir Bermasalah

Semua driver diset ke `database` secara lalai. Jika menggunakan `redis`, pastikan Redis sedang berjalan:

```bash
# (Windows) Pastikan redis-server berjalan
redis-server
```

### 7. Mixed Content / Monaco Editor tak load / "Flasher is not loaded"

Punca biasanya Laravel generate URL guna `http://` sedangkan halaman load guna `https://`.

**Semak:**
1. Pastikan `APP_ENV=production` dan `APP_URL=https://domain-anda.com` dalam `.env`.
2. Pastikan `URL::forceScheme('https')` aktif dalam `AppServiceProvider` untuk environment production.
3. Clear cache:
   ```bash
   php artisan config:cache
   php artisan view:clear
   php artisan optimize:clear
   ```
4. Jika server ada **load balancer / Cloudflare / reverse proxy**, Laravel mungkin perlu trust proxy. Tambah konfigurasi proxy dalam `bootstrap/app.php` atau `App\Http\Middleware\TrustProxies`.

### 8. `php artisan storage:link` Gagal / Filesystem Error

Punca biasa:

| Punca | Penjelasan |
|---|---|
| `public/storage` sudah wujud | Mungkin fail/folder biasa atau symlink rosak. |
| Shared hosting tak support symlink | Sesetengah hosting (terutama Windows/shared) disable symlink. |
| Permission denied | User hosting tak ada kebenaran cipta symlink. |
| `open_basedir` restriction | Hosting hadkan path yang boleh diakses PHP. |

**Langkah penyelesaian:**

1. **Hapus `public/storage` jika ada**, kemudian run semula:
   ```bash
   rm -rf public/storage
   php artisan storage:link
   ```

2. **Buat symlink secara manual** melalui SSH (Linux):
   ```bash
   ln -s /path/ke/project/storage/app/public /path/ke/project/public/storage
   ```

3. **Jika hosting tak support symlink** (biasa pada Windows/shared hosting), salin folder secara manual:
   ```bash
   cp -r storage/app/public/* public/storage/
   ```
   > **Nota:** Kaedah copy ini kurang ideal. Setiap kali ada upload baharu, kena salin semula.

4. **Pastikan `.env` filesystem betul:**
   ```env
   FILESYSTEM_DISK=local
   ```

5. Jika masih gagal, kemungkinan restriction dari hosting provider. Hubungi support hosting untuk enable symlink atau naikkan `open_basedir` limit.

### 9. `tempnam(): file created in the system's temporary directory`

Error ini berlaku apabila PHP/Laravel tak boleh menulis ke temporary directory semasa compile Blade view.

**Punca biasa:**
- Permission directory `/tmp` tak boleh ditulis oleh user web server.
- Disk partition `/tmp` penuh.
- `open_basedir` restriction menghalang akses ke temporary directory.
- PHP `sys_temp_dir` / `upload_tmp_dir` tak betul.

**Langkah penyelesaian:**

1. **Pastikan `storage/framework/views` boleh ditulis:**
   ```bash
   chmod -R 775 storage bootstrap/cache
   ```

   Jika anda ada akses root, set ownership kepada user project + group web server:
   ```bash
   sudo chown -R nizarkhan:www-data /var/www/html/portal-v1/storage /var/www/html/portal-v1/bootstrap/cache
   sudo chmod -R 775 /var/www/html/portal-v1/storage /var/www/html/portal-v1/bootstrap/cache
   ```

   > Tukar `nizarkhan` kepada username project anda, dan `/var/www/html/portal-v1` kepada path sebenar project.

   Jika `chown` gagal dengan *Operation not permitted*, maksudnya anda bukan root. Dalam kes ini, minta admin hosting tukar ownership.

2. **Set custom temporary directory** dalam `php.ini` atau `.user.ini`:
   ```ini
   sys_temp_dir = /path/ke/project/storage/tmp
   upload_tmp_dir = /path/ke/project/storage/tmp
   ```
   Kemudian cipta directory dan set permission:
   ```bash
   mkdir -p storage/tmp
   chmod 775 storage/tmp
   ```

3. **Atau gunakan fix dalam `public/index.php`** (sudah ditambah dalam codebase):
   Kod ini memaksa Laravel guna `storage/tmp` sebagai temporary directory bila request masuk:
   ```php
   $customTempDir = __DIR__ . '/../storage/tmp';
   if (!is_dir($customTempDir)) {
       mkdir($customTempDir, 0775, true);
   }
   putenv('TMPDIR=' . $customTempDir);
   ini_set('sys_temp_dir', $customTempDir);
   ini_set('upload_tmp_dir', $customTempDir);
   ```

3. **Bersihkan temporary directory sistem** (jika ada akses root):
   ```bash
   rm -rf /tmp/*
   ```

4. **Check ruang disk**:
   ```bash
   df -h
   ```

5. Jika masih gagal, hubungi hosting provider. Tanya mereka:
   > *"PHP cannot write to the temporary directory. Please check permissions and open_basedir settings for my account."*

---

## Kebergantungan Penuh

### PHP (Composer)

| Pakej | Versi | Kegunaan |
|---|---|---|
| `laravel/framework` | ^13.0 | Rangka kerja utama |
| `spatie/laravel-permission` | ^7.3 | Peranan & kebenaran |
| `spatie/laravel-activitylog` | ^5.0 | Log aktiviti pengguna |
| `barryvdh/laravel-elfinder` | ^0.6.0 | Pengurus fail dalam talian |
| `php-flasher/flasher-laravel` | ^2.6 | Pemberitahuan sistem |
| `php-flasher/flasher-sweetalert-laravel` | ^2.6 | Dialog SweetAlert |
| `laravel/tinker` | ^3.0 | Shell interaktif Artisan |

### Node.js (NPM — Root Projek)

| Pakej | Versi | Kegunaan |
|---|---|---|
| `tailwindcss` | ^4.0 | Rangka kerja CSS utiliti |
| `vite` | ^8.0 | Pembina aset modular |
| `alpinejs` | ^3.15 | Rangka kerja JS ringan |
| `apexcharts` | ^5.12 | Carta interaktif |
| `chart.js` | ^4.5 | Carta kanvas |
| `grapesjs` | ^0.23 | Pembina halaman seret & lepas |
| `filepond` | ^4.32 | Pemuat naik fail responsif |
| `sortablejs` | ^1.15 | Isih seret & lepas |
| `sweetalert2` | ^11 | Dialog moden |
| `@fortawesome/fontawesome-free` | ^7 | Perpustakaan ikon |
| `@tailwindcss/vite` | ^4.0 | Pemalam Vite Tailwind |
| `laravel-vite-plugin` | ^3.0 | Pemalam Vite Laravel |

### Node.js (NPM — TailAdmin)

Tema pentadbiran di `public/tailadmin/` mempunyai set kebergantungan NPM sendiri. Rujuk `public/tailadmin/package.json` untuk butiran.

---

## Kemasukan Pantas (Quick Start)

```bash
# 1. Clone & masuk direktori
git clone <repository-url> cms-laravel
cd cms-laravel

# 2. Persediaan .env
cp .env.example .env
# Edit .env — tetapkan DB_DATABASE, DB_USERNAME, DB_PASSWORD

# 3. Pasang PHP & Node dependencies
composer install
npm install

# 4. Jana kunci aplikasi
php artisan key:generate

# 5. Cipta pangkalan data & jalankan migrasi
# (Cipta pangkalan data 'cms_laravel_v1' dalam MySQL dahulu)
php artisan migrate --seed

# 6. Bina tema admin & aset
cd public/tailadmin && npm install && npm run build && cd ../../
npm run build

# 7. Pautan storage
php artisan storage:link

# 8. Jalankan
php artisan serve
# Buka http://localhost:8000
```
