# Icon System - Font Awesome Integration

## Overview

Sistem ikon menggunakan **Font Awesome Free 7.x** yang dipasang melalui npm dan dibundel bersama Vite. Ikon disimpan dalam DB melalui kolom `menu_class` dan dirender secara dinamik di sidebar.

---

## 1. Install & Setup

### NPM Package
```bash
npm install @fortawesome/fontawesome-free@^7
```

### Import CSS
**WAJIB import dalam `resources/js/app.js`**, BUKAN dalam `app.css`.

Fail: `resources/js/app.js`
```js
import '@fortawesome/fontawesome-free/css/all.min.css';
```

**Kenapa tak boleh guna `app.css`?**
Tailwind v4 (`@tailwindcss/vite`) proses semua CSS dalam pipeline dan **tree-shake** class yang tak statik. Oleh kerana class FA dalam blade adalah dinamik (`{{ $item['icon'] }}`), Tailwind tak detect dan buang semua icon-specific rules. Akibatnya:
```css
/* Before (app.css - rosak) */
.fa-solid,.fa-regular,.fa-brands,.fa-classic,.fa):before{content:var(--fa)} /* :before → ):before */

/* After (app.js - betul) */
:is(.fas,.far,.fab,.fa-solid,.fa-regular,.fa-brands,.fa-classic,.fa):before{content:var(--fa)/""}
```

Dengan import dalam JS, Vite handle FA CSS sebagai external asset — Tailwind tak sentuh langsung.

CSS dibundel oleh Vite dan di-load secara global melalui:
```blade
@vite(['resources/js/app.js'])
```

---

## 2. Database

### Kolom
| Table | Column | Type | Contoh Value |
|---|---|---|---|
| `backend_menu` | `menu_class` | `string(50), nullable` | `fa-solid fa-users` |
| `frontend_menu` | `menu_class` | `string(50), nullable` | `fa-solid fa-home` |
| `ref` | `icon_name` | `string(255), nullable` | `fa-star` |

### Set Icon via Tinker
```php
# Activity Log
DB::table('backend_menu')->where('menu_id', 6)->update(['menu_class' => 'fa-solid fa-clock-rotate-left']);
# Roles
DB::table('backend_menu')->where('menu_id', 9)->update(['menu_class' => 'fa-solid fa-users-gear']);
# Permissions
DB::table('backend_menu')->where('menu_id', 10)->update(['menu_class' => 'fa-solid fa-shield-halved']);
# Auto Permissions
DB::table('backend_menu')->where('menu_id', 11)->update(['menu_class' => 'fa-solid fa-robot']);
# Roles & Permissions
DB::table('backend_menu')->where('menu_id', 8)->update(['menu_class' => 'fa-solid fa-user-lock']);
# Frontend (tukar dari menu-icon-frontend ke FA)
DB::table('backend_menu')->where('menu_id', 15)->update(['menu_class' => 'fa-solid fa-globe']);

\App\Http\Helpers\MenuHelper::bustCache();
```

---

## 3. Rendering Logic

Fail: `resources/views/backend/layouts/partials/sidebar-dynamic-items.blade.php`

### Level 0 (Parent Menu)
```
menu_class               → Hasil
──────────────────────────────────────────────────
menu-icon-backend        → SVG hardcoded (grid icon)
menu-icon-frontend       → SVG hardcoded (globe icon)
menu-icon-content        → SVG hardcoded (folder icon)
fa-solid fa-*            → <i> FontAwesome (warna text-brand-500 aktif / gray-500 inaktif)
null/kosong              → Tiada icon
```

### Level > 0 (Child Menu)
```
menu_class               → Hasil
──────────────────────────────────────────────────
menu-icon-*              → SVG hardcoded dalam <span class="h-4 w-4">
fa-solid fa-*            → <i> FontAwesome dalam <span class="h-4 w-4">
null/kosong (level 1)    → fa-solid fa-circle (solid, 6px)
null/kosong (level >1)   → fa-regular fa-circle (regular, 8px)
```

Semua child menu guna container tetap `h-4 w-4` + `mr-2` (16px + 8px) untuk konsistensi alignment.

### CSS untuk Child Menu FA Icon
Fail: `resources/views/backend/layouts/app.blade.php`
```css
.sidebar-fa-icon:not(svg) {
    font-size: 12px;
    color: inherit;
}
```

---

## 4. Code Explanation

### 4.1 Variable `$isFaIcon`
Fail: `sidebar-dynamic-items.blade.php:8-10`

```php
$isFaIcon = !empty($item['icon']) && !in_array($item['icon'], [
    'menu-icon-backend', 'menu-icon-frontend', 'menu-icon-content'
]);
```

**Tujuan:** Membezakan 3 jenis icon dalam satu pembolehubah:
- `menu-icon-backend/frontend/content` → SVG hardcoded (`$isFaIcon = false`)
- `fa-solid fa-*` / `fa-regular fa-*` → FontAwesome (`$isFaIcon = true`)
- `null` / kosong → guna bullet default

---

### 4.2 Level 0 — Parent Menu (line 31-32)

**Before (masalah):**
```blade
@elseif (!empty($item['icon']))
    <i class="{{ $item['icon'] }} {{ $active ? 'menu-item-icon-active' : 'menu-item-icon-inactive' }}"></i>
@else
    <svg>fallback...</svg>
@endif
```

**Kenapa gagal:** `menu-item-icon-active` / `menu-item-icon-inactive` guna CSS `fill-*`. `fill` hanya kerja untuk SVG, **tidak** untuk `<i>`. FontAwesome guna `color`, bukan `fill`.

**After (fix):**
```blade
@elseif ($isFaIcon)
    <i class="{{ $item['icon'] }} {{ $active ? 'text-brand-500 dark:text-brand-400' : 'text-gray-500 group-hover:text-gray-700 dark:text-gray-400 dark:group-hover:text-gray-300' }}"></i>
@endif
```

**Perubahan:**
| Item | Before | After |
|---|---|---|
| Condition | `!empty($item['icon'])` | `$isFaIcon` (specific) |
| Color class | `menu-item-icon-active/inactive` (fill) | `text-brand-500` / `text-gray-500` (color) |
| Fallback SVG | Ada (default icon) | Dibuang (tiada icon kalau null) |

---

### 4.3 Level > 0 — Child Menu

**Before (masalah):**
```blade
@if (!empty($item['icon']))
    <span class="mr-2 inline-flex h-5 w-5 items-center justify-center">
        @if (...menu-icon-backend...) <svg>...</svg>
        @else <i class="{{ $item['icon'] }} text-xs"></i>
        @endif
    </span>
@endif
<span>{{ $item['label'] }}</span>
```

**Masalah:**
1. Items tanpa icon takde span — text start posisi berbeza
2. `<i>` guna `fill-*` class yang tak support FA
3. Takde default bullet/icon untuk item kosong

**After (iterasi 1 — negative margin):**
```blade
@if ($isFaIcon)
    <i class="{{ $item['icon'] }} sidebar-fa-icon" style="margin-left: -26px"></i>
@elseif (!empty($item['icon']))
    {{-- menu-icon-backend/frontend/content SVG --}}
@endif
<span>{{ $item['label'] }}</span>
```
**Masalah:** `margin-left: -26px` ter-clip oleh `overflow-hidden` pada nested submenu (level > 1).

**After (final — fixed container):**
```blade
<span class="mr-2 inline-flex h-4 w-4 items-center justify-center">
    @if ($isFaIcon)
        <i class="{{ $item['icon'] }} sidebar-fa-icon"></i>
    @elseif (!empty($item['icon']))
        {{-- menu-icon-backend/frontend/content SVG --}}
    @else
        @if ($level === 1)
            <i class="fa-solid fa-circle sidebar-fa-icon" style="font-size: 6px;"></i>
        @else
            <i class="fa-regular fa-circle sidebar-fa-icon" style="font-size: 8px;"></i>
        @endif
    @endif
</span>
<span>{{ $item['label'] }}</span>
```

**Kelebihan:**
1. Semua item guna container tetap `h-4 w-4` + `mr-2` (24px) → alignment konsisten
2. Takde negative margin → tak kena clip oleh `overflow-hidden`
3. Items tanpa icon → FA circle (solid level 1, regular level > 1)

---

### 4.4 CSS `.sidebar-fa-icon` (app.blade.php)

```css
.sidebar-fa-icon:not(svg) {
    font-size: 12px;
    color: inherit;
}
```

Warna diwarisi dari parent `<a>`:
- `.menu-dropdown-item-active` → `color: var(--color-brand-500)` (#465FFF)
- `.menu-dropdown-item-inactive` → `color: var(--color-gray-700)` (#344054)

---

## 5. Complete Flow

```
Database (backend_menu.menu_class)
    ↓
MenuHelper::getMenu()
  → query backend_menu + role_mapping
  → cache ikut role user
  → return array['icon' => $menu->menu_class]
    ↓
sidebar.blade.php
  → $dynamicMenus = MenuHelper::getMenu()
  → @include('sidebar-dynamic-items', ['items' => $dynamicMenus, 'level' => 0])
    ↓
sidebar-dynamic-items.blade.php
  → $isFaIcon = !empty($icon) && !in_array($icon, ['menu-icon-*'])
    ↓
  Level 0 (Parent)
    ├─ menu-icon-backend     → <svg>hardcoded backend SVG</svg>
    ├─ menu-icon-frontend    → <svg>hardcoded frontend SVG</svg>
    ├─ menu-icon-content     → <svg>hardcoded content SVG</svg>
    ├─ $isFaIcon (true)      → <i class="fa-solid fa-xxx
    │                           text-brand-500/text-gray-500">
    └─ null                  → (nothing)
    ↓
  Level > 0 (Child)
    ├─ $isFaIcon (true)      → <span class="h-4 w-4"><i class="fa-solid fa-xxx sidebar-fa-icon"></i></span>
    ├─ menu-icon-*           → <span class="h-4 w-4"><svg>hardcoded</svg></span>
    ├─ null + level 1        → <span class="h-4 w-4"><i class="fa-solid fa-circle" style="font-size:6px"></i></span>
    └─ null + level > 1      → <span class="h-4 w-4"><i class="fa-regular fa-circle" style="font-size:8px"></i></span>
```

---

## 6. Cara Guna (Backend Menu)

### Tambah Icon Baru
1. Admin panel → Backend Menu → Edit menu
2. Isi field **Menu Class** dengan class FontAwesome, contoh: `fa-solid fa-users-gear`
3. Simpan
4. Clear cache: `\App\Http\Helpers\MenuHelper::bustCache()`

### Senarai Class Prefix
| Prefix | Contoh | Jenis |
|---|---|---|
| `fa-solid fa-*` | `fa-solid fa-user` | Free (solid) |
| `fa-regular fa-*` | `fa-regular fa-user` | Free (regular) |
| `fa-brands fa-*` | `fa-brands fa-github` | Free (brands) |
| `menu-icon-*` | `menu-icon-backend` | Built-in SVG (3 sahaja) |

### Icon Popular untuk Rujukan
```
fa-solid fa-dashboard        fa-solid fa-users-gear
fa-solid fa-user             fa-solid fa-shield-halved
fa-solid fa-lock             fa-solid fa-robot
fa-solid fa-gear             fa-solid fa-clock-rotate-left
fa-solid fa-globe            fa-solid fa-file-lines
fa-solid fa-folder-open      fa-solid fa-image
fa-solid fa-link             fa-solid fa-newspaper
fa-solid fa-bars             fa-solid fa-eye
fa-regular fa-star           fa-solid fa-route
```

---

## 7. CSS Color Scheme

### Level 0
| State | Color | CSS Class |
|---|---|---|
| Aktif | `brand-500` (#465FFF) | `text-brand-500 dark:text-brand-400` |
| Inaktif | `gray-500` (#667085) | `text-gray-500 group-hover:text-gray-700` |

### Level > 0 (Child)
Warna diwarisi (inherit) dari parent `<a>`:
| State | Color |
|---|---|
| Aktif | `brand-500` (#465FFF) |
| Inaktif | `gray-700` (#344054) |

---

## 8. Files Changed

| File | Perubahan |
|---|---|
| `resources/js/app.js` | Tambah `import '@fortawesome/fontawesome-free/css/all.min.css'` |
| `resources/css/app.css` | Buang `@import "@fortawesome/..."` — pindah ke app.js |
| `resources/views/backend/layouts/app.blade.php` | Tambah CSS `.sidebar-fa-icon`, buang CDN FA |
| `resources/views/backend/layouts/partials/sidebar-dynamic-items.blade.php` | Ubah render FA icon ganti bullet, guna fixed container `h-4 w-4`, tambah default FA circle |
| `public/tailadmin/src/css/style.css` | Buang rules `.menu-dropdown` (list-style, margin-left) |
| `public/tailadmin/build/style.css` | Buang rules `.menu-dropdown` (list-style, margin-left) |

---

## 9. Troubleshooting

**Icon tak muncul**
1. Check `menu_class` ada value kat DB
2. Pastikan cache dibust: `MenuHelper::bustCache()`
3. Hard refresh browser (Ctrl+Shift+R)
4. Check role mapping — menu kena assign dulu baru nampak

**Icon keluar tapi warna salah**
- Level 0: guna `text-brand-500` / `text-gray-500` (bukan `fill-*`)
- Level > 0: guna `color: inherit` — pastikan parent `<a>` ada class `menu-dropdown-item-active/inactive`

**Icon terpotong / clipping**
- Jangan guna `margin-left` negatif / `position: absolute` — akan ter-clip oleh `overflow-hidden` pada nested submenu
- Guna **fixed container** `h-4 w-4` + `mr-2`: semua item ada ruang icon yang sama, tanpa positioning negatif

**Icon tak muncul selepas npm install / build**
- Mungkin Tailwind v4 tree-shake FA CSS. Pastikan FA diimport dalam **`app.js`**, bukan `app.css`:
  ```js
  // ✅ BETUL - app.js
  import '@fortawesome/fontawesome-free/css/all.min.css';
  ```
  ```css
  /* ❌ SALAH - app.css (Tailwind v4 akan rosakkan) */
  @import "@fortawesome/fontawesome-free/css/all.min.css";
  ```
- Rebuild: `npm run build`
