# CapEx v2 — Sticky Scrollbar & Blendco Order Filter Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add an always-accessible horizontal scrollbar to the Planning table and add a Blendco Order dropdown filter.

**Architecture:** Two independent changes to the same two files. The scrollbar fix adds a mirror div + bidirectional JS scroll sync above the existing `overflow-x: auto` table wrapper. The filter follows the existing `<details>/<summary>/checkbox-list` + `$_GET` + SQL WHERE pattern used by every other planning filter.

**Tech Stack:** PHP, vanilla JS, MySQL (via `mysqli`). No build step — edit files directly in `public/finance/capex_v2/`.

---

## File Map

| File | Change |
|------|--------|
| `public/finance/capex_v2/capex_planning_fragment.php` | Add mirror div + sync JS above table; add Blendco filter cell in Row 2; add `plan_blendco` to `arrayKeys` |
| `public/finance/capex_v2/api/capex_planning_filters.php` | Add `$plan_filter_blendco` var and WHERE clause |

---

## Task 1: Add Blendco Order variable and WHERE clause to filters

**Files:**
- Modify: `public/finance/capex_v2/api/capex_planning_filters.php`

- [ ] **Step 1: Open the file and locate the Quote Confirmed filter block (near the bottom, ~line 132)**

The file ends with the Quote Confirmed filter and `$plan_order`. Add the Blendco filter between them.

- [ ] **Step 2: Add `$plan_filter_blendco` variable at the top of the file alongside the other variables (after line 20)**

In the variable declaration block (lines 3–20), add after `$plan_filter_year`:

```php
$plan_filter_blendco = $_GET['plan_blendco'] ?? [];
```

- [ ] **Step 3: Add the WHERE clause after the Quote Confirmed filter block (before `$plan_order`)**

After the closing `}` of the Quote Confirmed block (~line 138), add:

```php
// Blendco Order Filter
if (!empty($plan_filter_blendco)) {
    $formatted_blendco = '("' . implode('","', $plan_filter_blendco) . '")';
    $plan_query_search .= " AND po_list.blendco_order IN $formatted_blendco ";
    $plan_filtered .= " Blendco Order(" . $formatted_blendco . ")";
}
```

- [ ] **Step 4: Verify the file ends correctly**

After your edit, the end of the file should read:

```php
// Blendco Order Filter
if (!empty($plan_filter_blendco)) {
    $formatted_blendco = '("' . implode('","', $plan_filter_blendco) . '")';
    $plan_query_search .= " AND po_list.blendco_order IN $formatted_blendco ";
    $plan_filtered .= " Blendco Order(" . $formatted_blendco . ")";
}

$plan_order = ' ORDER BY li.locationID';
```

---

## Task 2: Add Blendco Order filter cell to the Planning filter bar

**Files:**
- Modify: `public/finance/capex_v2/capex_planning_fragment.php`

- [ ] **Step 1: Locate the Last Updated filter cell (~line 318)**

```html
<div class="capex-filter-cell" style="flex-grow:0;">
    <!-- Last Updated Filter -->
    <b>Last Updated</b><br>
    <input type="date" name="plan_updated_start" ...
```

- [ ] **Step 2: Insert the Blendco Order filter cell immediately before the Last Updated filter cell**

```php
                <div class="capex-filter-cell">
                    <!-- Blendco Order Filter -->
                    <b>Blendco Order</b><br>
                    <details>
                        <summary>Select Blendco Order</summary>
                        <div class="checkbox-list">
                            <?php
                            $get_blendco = mysqli_query($conn, "SELECT DISTINCT blendco_order FROM capex_planning WHERE blendco_order IS NOT NULL AND blendco_order != '' ORDER BY blendco_order") or die(mysqli_error($conn));
                            while ($row_blendco = mysqli_fetch_array($get_blendco)) {
                                $blendco = (string)($row_blendco['blendco_order'] ?? '');
                                $blendco_checked = in_array($blendco, $plan_filter_blendco) ? 'checked' : '';
                                echo '<label><input type="checkbox" name="plan_blendco[]" value="' . htmlspecialchars($blendco) . '" ' . $blendco_checked . '> ' . htmlspecialchars($blendco) . '</label>';
                            }
                            ?>
                        </div>
                    </details>
                </div>
```

- [ ] **Step 3: Add `'plan_blendco'` to the `arrayKeys` array in `refreshPlanningTable()` (~line 406)**

Find:
```js
const arrayKeys  = ['plan_status', 'plan_requestor', 'plan_location', 'plan_type',
                    'plan_msa', 'plan_commitment', 'plan_ad', 'plan_rd', 'plan_category',
                    'plan_deploy', 'plan_quote_confirmed', 'plan_priority', 'plan_year'];
```

Replace with:
```js
const arrayKeys  = ['plan_status', 'plan_requestor', 'plan_location', 'plan_type',
                    'plan_msa', 'plan_commitment', 'plan_ad', 'plan_rd', 'plan_category',
                    'plan_deploy', 'plan_quote_confirmed', 'plan_priority', 'plan_year',
                    'plan_blendco'];
```

- [ ] **Step 4: Verify manually in the browser**

1. Open `http://whitewater-secure/public/finance/capex_v2/capex_planning.php`
2. Confirm "Blendco Order" filter appears in the filter bar
3. Click the dropdown — confirm it shows distinct values from the DB
4. Select a value, click Filter — confirm the Applied Filtering bar shows `Blendco Order(...)` and the table rows are filtered correctly
5. Click Clear Filters — confirm filter resets

---

## Task 3: Add always-accessible horizontal scrollbar (dual-scroll sync)

**Files:**
- Modify: `public/finance/capex_v2/capex_planning_fragment.php`

- [ ] **Step 1: Add `id` to the existing table wrapper div (~line 343)**

Find:
```html
<div style="overflow-x: auto; -webkit-overflow-scrolling: touch;">
```

Replace with:
```html
<div id="planningTopScroll" style="overflow-x: auto; overflow-y: hidden; height: 14px; margin-bottom: 2px;">
    <div id="planningTopScrollInner" style="height: 1px;"></div>
</div>
<div id="planningTableScroll" style="overflow-x: auto; -webkit-overflow-scrolling: touch;">
```

- [ ] **Step 2: Add `syncPlanningScroll()` function to the existing `<script>` block (~line 377)**

Locate the opening `<script>` tag of the permissions/refresh script block. Add this function before `refreshPlanningTable()`:

```js
    function syncPlanningScroll() {
        const topScroll = document.getElementById('planningTopScroll');
        const tableScroll = document.getElementById('planningTableScroll');
        const inner = document.getElementById('planningTopScrollInner');
        if (!topScroll || !tableScroll || !inner) return;

        const table = document.getElementById('tbl_exporttable_to_xls2');
        inner.style.width = (table ? table.scrollWidth : tableScroll.scrollWidth) + 'px';

        let syncing = false;
        topScroll.addEventListener('scroll', function () {
            if (syncing) return;
            syncing = true;
            tableScroll.scrollLeft = topScroll.scrollLeft;
            syncing = false;
        });
        tableScroll.addEventListener('scroll', function () {
            if (syncing) return;
            syncing = true;
            topScroll.scrollLeft = tableScroll.scrollLeft;
            syncing = false;
        });
    }
```

- [ ] **Step 3: Chain `syncPlanningScroll()` after `refreshPlanningTable()` resolves**

Find the `DOMContentLoaded` listener that calls `refreshPlanningTable`:
```js
    document.addEventListener("DOMContentLoaded", refreshPlanningTable);
```

Replace with:
```js
    document.addEventListener("DOMContentLoaded", function () {
        refreshPlanningTable().then(syncPlanningScroll);
    });
```

- [ ] **Step 4: Also call `syncPlanningScroll()` in the storage listener after table refresh**

Find:
```js
    window.addEventListener("storage", function(e) {
        if (e.key === "capexRefresh" && e.newValue === "planning") {
            refreshPlanningTable();
            localStorage.removeItem("capexRefresh");
        }
    });
```

Replace with:
```js
    window.addEventListener("storage", function(e) {
        if (e.key === "capexRefresh" && e.newValue === "planning") {
            refreshPlanningTable().then(syncPlanningScroll);
            localStorage.removeItem("capexRefresh");
        }
    });
```

- [ ] **Step 5: Verify manually in the browser**

1. Open `http://whitewater-secure/public/finance/capex_v2/capex_planning.php`
2. Confirm a thin horizontal scrollbar appears directly above the table header
3. Scroll that top bar left/right — confirm the table scrolls in sync
4. Scroll the table left/right (at the bottom) — confirm the top bar moves in sync
5. Open `http://whitewater-secure/public/finance/capex_v2/tracker.php` → Planning tab
6. Confirm the same top scrollbar behavior works in the embedded (tab2) context

---

## Task 4: Commit

- [ ] **Step 1: Stage and commit both files**

```bash
cd /c/Users/Eric/Workspace/Git/whitewater-secure
git add public/finance/capex_v2/capex_planning_fragment.php
git add public/finance/capex_v2/api/capex_planning_filters.php
git commit -m "feat(capex-v2): sticky top scrollbar + blendco order filter on planning tab"
```
