# 📋 Implementation Plan: Refresh Action Bar Tanpa Reload Halaman

## Tujuan
Setiap ada perubahan di `estimates/details` (tambah item, hapus item, edit qty, dll), tombol **Tindakan** di `estimates/view.php` ikut diperbarui tanpa reload halaman penuh.

---

## Analisis Kondisi Saat Ini

Tombol **Tindakan** dirender PHP di [`view.php` L187–461](file:///z:/san_ibb_2jul/app/Views/estimates/view.php#L187-L461) dengan **11 variabel** dari server:

| Variabel PHP | Sumber | Berpengaruh ke tombol |
|---|---|---|
| `$has_items` (`$jml_item > 0`) | count items dari DB | ✅ Mark as Won/Send to Client |
| `$is_draft_or_sent` | `estimate_info->status` | ✅ Hampir semua tombol |
| `$is_estimate_editable` | `_is_estimate_editable()` | ✅ Edit, Clone, Won, Declined |
| `$has_unresolved_custom_items` | `get_unresolved_count()` | ✅ Mark as Won |
| `$is_admin` | `login_user->is_admin` | ✅ Mark as Declined |
| `$client_info->is_lead` | DB client | ✅ Send to Lead vs Client |
| `$show_invoice_option` | settings + permission | ✅ Create Invoice |
| `$can_create_projects` | permission | ✅ Create Project |

Karena logikanya kompleks dan bergantung DB, **action bar harus di-generate server-side** setiap ada perubahan.

---

## Rencana Implementasi

### 1. Buat Partial View — `estimate_action_bar.php` [NEW]

Extract kode action bar dari `view.php` baris 187–461 ke file partial terpisah:

#### [NEW] `estimate_action_bar.php`
- Path: `app/Views/estimates/estimate_action_bar.php`  
- Isi: Semua kode PHP/HTML yang menghasilkan `<div class='title-button-group'>` + dropdown Tindakan
- Menerima variabel: `$estimate_info`, `$jml_item`, `$is_estimate_editable`, `$has_unresolved_custom_items`, `$is_admin`, `$client_info`, `$estimate_status`, `$show_invoice_option`, `$can_create_projects`, `$is_estimate_editable`

---

### 2. Update `view.php` — Wrapper ID + include partial [MODIFY]

#### [MODIFY] [`view.php`](file:///z:/san_ibb_2jul/app/Views/estimates/view.php)
- Ganti baris 187–461 (render inline) dengan:
```php
// Beri ID wrapper agar bisa di-replace via AJAX
$view .= "<div id='estimate-action-bar-wrapper'>";
$view .= view('estimates/estimate_action_bar', $action_bar_data);
$view .= "</div>";
```
- Tidak ada perubahan fungsional, hanya penambahan wrapper `id="estimate-action-bar-wrapper"`

---

### 3. Tambah Endpoint Controller — `get_action_bar()` [NEW METHOD]

#### [MODIFY] [`Estimates.php`](file:///z:/san_ibb_2jul/app/Controllers/Estimates.php)

Tambah fungsi baru setelah `get_estimate_status_bar()` (sekitar baris 6110):

```php
/**
 * Return HTML partial untuk action bar (dropdown Tindakan)
 * Dipanggil via AJAX setelah ada perubahan item di estimates/details
 */
public function get_action_bar($estimate_id = 0)
{
    validate_numeric_value($estimate_id);
    $this->validate_estimate_access($estimate_id);

    $view_data = get_estimate_making_data($estimate_id);
    if (!$view_data) { show_404(); }

    $jml_item = count($view_data['estimate_items'] ?? []);
    $unresolved = $this->Estimate_custom_items_model->get_unresolved_count($estimate_id);

    $view_data['jml_item']                    = $jml_item;
    $view_data['has_unresolved_custom_items'] = $unresolved > 0;
    $view_data['estimate_status']             = $this->_get_estimate_status_label($view_data['estimate_info'], false);
    $view_data['is_estimate_editable']        = $this->_is_estimate_editable($estimate_id);
    $view_data['is_admin']                    = $this->login_user->is_admin;
    $view_data['show_invoice_option']         = (get_setting('module_invoice') && $this->get_access_info('invoice')->access_type == 'all');
    $view_data['can_create_projects']         = $this->can_create_projects();

    return $this->template->view('estimates/estimate_action_bar', $view_data);
}
```

---

### 4. Tambah Route (jika diperlukan)

#### [MODIFY] `app/Config/Routes.php`
Cek apakah routing auto-discovery aktif. Jika ya, tidak perlu tambah route manual.

---

### 5. Tambah Fungsi JS Global `refreshEstimateActionBar()` di `view.php`

#### [MODIFY] [`view.php`](file:///z:/san_ibb_2jul/app/Views/estimates/view.php)

Tambah fungsi global yang dipanggil dari `details.php` (dan mana saja yang perlu):

```js
// Fungsi global untuk refresh action bar dari AJAX
window.refreshEstimateActionBar = function (estimateId) {
    $.get('<?php echo get_uri("estimates/get_action_bar"); ?>/' + estimateId, function (html) {
        if (html) {
            $('#estimate-action-bar-wrapper').html(html);
            // Re-init feather icons & popovers yang ada di dropdown
            if (window.feather) feather.replace();
            initDisabledActionPopovers(document.getElementById('estimate-action-bar-wrapper'));
        }
    });
};
```

---

### 6. Panggil `refreshEstimateActionBar()` dari setiap event di `details.php` dan `view.php`

#### Titik-titik yang perlu ditambahkan panggilan:

| Lokasi | Event | File |
|--------|-------|------|
| Setelah AJAX update qty sukses | `success callback update_item_field` | `view.php` L829 |
| Setelah item ditambahkan | `success callback add_item` | `details.php` |
| Setelah item dihapus | `success callback delete_item` | `details.php` |
| Setelah custom item di-mapping | `success callback map_custom_item` | `details.php` |

Semua cukup tambah **1 baris** di success callback masing-masing:
```js
if (typeof window.refreshEstimateActionBar === 'function') {
    window.refreshEstimateActionBar(estimateId);
}
```

---

## Alur Setelah Implementasi

```
User tambah/hapus/edit item di details
    ↓
AJAX success callback di details.php / view.php
    ↓
window.refreshEstimateActionBar(estimateId) dipanggil
    ↓
GET estimates/get_action_bar/{id}
    ↓
Controller load fresh data dari DB
    ↓
Render estimate_action_bar.php (PHP partial)
    ↓
Return HTML
    ↓
JS: $('#estimate-action-bar-wrapper').html(html)
    ↓
feather.replace() + re-init popovers
    ↓
Tombol Tindakan tampil up-to-date ✅ (tanpa reload)
```

---

## File yang Diubah

| File | Aksi | Deskripsi |
|------|------|-----------|
| [`app/Views/estimates/estimate_action_bar.php`](file:///z:/san_ibb_2jul/app/Views/estimates/) | **[NEW]** | Partial view action bar |
| [`app/Views/estimates/view.php`](file:///z:/san_ibb_2jul/app/Views/estimates/view.php) | **[MODIFY]** | Wrapper ID + fungsi JS global |
| [`app/Controllers/Estimates.php`](file:///z:/san_ibb_2jul/app/Controllers/Estimates.php) | **[MODIFY]** | Tambah `get_action_bar()` |
| [`app/Views/estimates/details.php`](file:///z:/san_ibb_2jul/app/Views/estimates/details.php) | **[MODIFY]** | Panggil `refreshEstimateActionBar()` di tiap event sukses |

> **[!NOTE]**
> Tidak ada perubahan DB, tidak ada perubahan Model. Hanya perubahan di layer View dan Controller (endpoint baru).

## Verification Plan

1. Edit qty → tombol Tindakan terupdate (terutama `has_items` dan `has_unresolved_custom_items`)
2. Tambah item → tombol "Tandai sebagai disetujui (won)" berubah state
3. Hapus semua item → tombol "Kirim ke klien" menjadi disabled
4. Map custom item → tombol "Tandai sebagai disetujui (won)" aktif kembali
