# IAP Leadership Review Notification — 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:** When an HR editor sets an application to "Leadership Review", an inline panel expands allowing selection of exec recipients (pre-checked) and an optional custom message, then sends individual SendGrid emails on save.

**Architecture:** New `iap_leadership_recipients` DB table holds the exec list. `application_detail.php` loads recipients and renders the hidden inline panel; JS toggles it on status select change and validates before submit. `sync_application_status.php` accepts the new POST params, whitelist-validates recipient emails against the DB, queries applicant details, and sends one SendGrid email per recipient.

**Tech Stack:** PHP, MySQL, jQuery, SendGrid (`\SendGrid\Mail\Mail`)

---

## File Map

| File | Change |
|------|--------|
| DB | CREATE `iap_leadership_recipients` + seed Cassie + Carmen |
| `app/HR/IAP/application_detail.php` | Load recipients; add inline notify panel HTML; update JS |
| `app/HR/IAP/sync_application_status.php` | Accept notify POST params; server-side whitelist; SendGrid sends |

---

## Task 1: Create DB Table and Seed Data

**Run against production MySQL** (`whitewater` DB) via MySQL CLI or phpMyAdmin.

- [ ] **Step 1: Run the CREATE TABLE statement**

```sql
CREATE TABLE iap_leadership_recipients (
    id         INT AUTO_INCREMENT PRIMARY KEY,
    name       VARCHAR(100)  NOT NULL,
    email      VARCHAR(255)  NOT NULL,
    active     TINYINT(1)    NOT NULL DEFAULT 1,
    sort_order INT           NOT NULL DEFAULT 0
);
```

- [ ] **Step 2: Seed initial recipients**

```sql
INSERT INTO iap_leadership_recipients (name, email, sort_order) VALUES
    ('Cassie Myers',    'cmyers@whitewatercw.com', 1),
    ('Carmen Trujillo', 'carmen@whitewatercw.com', 2);
```

- [ ] **Step 3: Verify**

```sql
SELECT * FROM iap_leadership_recipients;
```

Expected: 2 rows, both `active = 1`.

---

## Task 2: Update application_detail.php

**File:** `C:/Users/Eric/Workspace/Git/whitewater-secure/app/HR/IAP/application_detail.php`

- [ ] **Step 1: Load recipients from DB at top of file**

After `$conn` is created and permission check passes (around line 20, after `$permStmt->close()`), add:

```php
// Load active leadership recipients for notification panel
$recipientsResult    = $conn->query("SELECT name, email FROM iap_leadership_recipients WHERE active = 1 ORDER BY sort_order");
$leadership_recipients = [];
while ($lr = $recipientsResult->fetch_assoc()) {
    $leadership_recipients[] = $lr;
}
```

- [ ] **Step 2: Add inline notification panel to HTML**

Locate the Status Management section. The `.status-form-row` div contains the status select and notes textarea side-by-side. Insert the panel immediately after the closing `</div>` of `.status-form-row` (before the Update Status button):

```php
            </div><!-- /.status-form-row -->
            <div id="leadership-notify" style="display:none; margin-top:14px; padding:12px; background:#fff8e1; border:1px solid #ffc107; border-radius:4px;">
                <b style="font-size:13px;">Notify Leadership</b>
                <div style="margin-top:8px;">
                    <?php foreach ($leadership_recipients as $lr): ?>
                    <label style="display:block; font-size:13px; margin-bottom:4px;">
                        <input type="checkbox" name="notify_recipients[]" value="<?=htmlspecialchars($lr['email'], ENT_QUOTES | ENT_HTML5, 'UTF-8')?>" checked>
                        <?=htmlspecialchars($lr['name'], ENT_QUOTES | ENT_HTML5, 'UTF-8')?>
                    </label>
                    <?php endforeach; ?>
                </div>
                <div style="margin-top:10px;">
                    <label style="display:block; font-size:13px; font-weight:bold; margin-bottom:4px;">Custom Message (optional)</label>
                    <textarea name="notify_message" rows="3" style="width:100%; padding:6px 8px; border:1px solid #ccc; border-radius:3px; font-size:13px; box-sizing:border-box;" placeholder="Add a note for the leadership team..."></textarea>
                </div>
                <span id="notify-error" style="color:#dc3545; font-size:12px; display:none;">At least one recipient is required.</span>
            </div>
```

- [ ] **Step 3: Update the JS block**

Replace the existing `$('#statusForm').submit(...)` handler and add the status select change handler. The full updated `<script>` block:

```javascript
<script>
    $('#saveChecks').click(function () {
        $.ajax({
            url: 'iap.php?page=sync_eligibility',
            method: 'POST',
            data: new FormData($('#eligibilityForm')[0]),
            processData: false,
            contentType: false,
            success: function () { alert('Saved'); location.reload(); },
            error: function () { alert('Error saving checks'); }
        });
    });

    // Show/hide leadership notify panel
    $('select[name="new_status"]').on('change', function () {
        if ($(this).val() === 'Leadership Review') {
            $('#leadership-notify').show();
        } else {
            $('#leadership-notify').hide();
        }
    });

    $('#statusForm').submit(function (e) {
        e.preventDefault();

        // Validate: if Leadership Review, require at least one recipient checked
        if ($('select[name="new_status"]').val() === 'Leadership Review') {
            if ($('#leadership-notify input[name="notify_recipients[]"]:checked').length === 0) {
                $('#notify-error').show();
                return;
            }
        }
        $('#notify-error').hide();

        $.ajax({
            url: 'iap.php?page=sync_status',
            method: 'POST',
            data: new FormData(this),
            processData: false,
            contentType: false,
            success: function () { alert('Status updated'); location.reload(); },
            error: function () { alert('Error updating status'); }
        });
    });
</script>
```

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

Open `http://whitewater-secure/public/hr/iap.php?page=detail&id=1`

Expected:
- No notify panel visible on load
- Select "Leadership Review" → yellow panel appears with Cassie + Carmen pre-checked
- Select any other status → panel hides
- Uncheck all recipients, try to submit → "At least one recipient is required." error shown, submit blocked

---

## Task 3: Update sync_application_status.php

**File:** `C:/Users/Eric/Workspace/Git/whitewater-secure/app/HR/IAP/sync_application_status.php`

- [ ] **Step 1: Add notify POST params near top of file**

After the existing `$notes = $_POST['notes'] ?? '';` line (line 17), add:

```php
$notify_recipients = $_POST['notify_recipients'] ?? [];
$notify_message    = trim($_POST['notify_message'] ?? '');
```

- [ ] **Step 2: Add notification block inside the success branch**

Inside the `if ($updateStmt->execute())` block, after `$logStmt->execute(); $logStmt->close();` and before `echo "Success"`, add:

```php
    // Send leadership notifications when status moves to Leadership Review
    if ($new_status === 'Leadership Review' && !empty($notify_recipients)) {
        // Server-side whitelist: only allow emails present in active recipients table
        $valid_emails = [];
        $validResult  = $conn->query("SELECT email FROM iap_leadership_recipients WHERE active = 1");
        while ($vr = $validResult->fetch_assoc()) {
            $valid_emails[] = $vr['email'];
        }
        $safe_recipients = array_intersect($notify_recipients, $valid_emails);

        if (!empty($safe_recipients)) {
            // Fetch applicant details for email body
            $appStmt = $conn->prepare("SELECT first_name, last_name, position_applying_for, desired_location FROM internal_applications WHERE application_id = ?");
            $appStmt->bind_param('i', $application_id);
            $appStmt->execute();
            $app_row = $appStmt->get_result()->fetch_assoc();
            $appStmt->close();

            if ($app_row) {
                $esc        = fn($v) => htmlspecialchars((string)$v, ENT_QUOTES | ENT_HTML5, 'UTF-8');
                $detail_url = 'https://intranet.whitewatercw.com/hr/iap.php?page=detail&id=' . (int)$application_id;
                $subject    = 'Leadership Review — ' . $esc($app_row['first_name']) . ' ' . $esc($app_row['last_name']);
                $body       = '<h2>Leadership Review — ' . $esc($app_row['first_name']) . ' ' . $esc($app_row['last_name']) . '</h2>'
                            . '<p><strong>Position Applied:</strong> ' . $esc($app_row['position_applying_for']) . '</p>'
                            . '<p><strong>Desired Location:</strong> ' . $esc($app_row['desired_location']) . '</p>'
                            . (!empty($notify_message) ? '<p><strong>Note:</strong> ' . $esc($notify_message) . '</p>' : '')
                            . '<p><a href="' . $esc($detail_url) . '">View Application</a></p>';

                $sendgrid = new \SendGrid(envv('SENDGRID_API_KEY'));
                foreach ($safe_recipients as $recipient_email) {
                    $mail = new \SendGrid\Mail\Mail();
                    $mail->setFrom('noreply@whitewatercw.com', 'Internal Applications');
                    $mail->setSubject($subject);
                    $mail->addTo($recipient_email);
                    $mail->addContent('text/html', $body);
                    $response = $sendgrid->send($mail);
                    if ($response->statusCode() >= 400) {
                        error_log('SendGrid IAP leadership notify failed for ' . $recipient_email . ': ' . $response->statusCode() . ' ' . $response->body());
                    }
                }
            }
        }
    }
```

- [ ] **Step 3: Verify PHP syntax**

```bash
php -l "C:/Users/Eric/Workspace/Git/whitewater-secure/app/HR/IAP/sync_application_status.php"
```

Expected: `No syntax errors detected`

---

## Task 4: End-to-End Verification (manual)

- [ ] **Step 1: Open an application detail page**

`http://whitewater-secure/public/hr/iap.php?page=detail&id=1` (use any real application ID)

- [ ] **Step 2: Test panel show/hide**

Select "Leadership Review" → panel appears, Cassie + Carmen pre-checked.
Select "Processing" → panel hides.

- [ ] **Step 3: Test recipient validation**

Select "Leadership Review", uncheck both recipients, click Update Status → error shown, no submission.

- [ ] **Step 4: Test successful submission**

Select "Leadership Review", leave both checked, add a note "Test notification", click Update Status → alert "Status updated", page reloads, Action History shows status change.

- [ ] **Step 5: Verify emails received**

Check cmyers@whitewatercw.com and carmen@whitewatercw.com inboxes for subject "Leadership Review — [Applicant Name]" with correct position, location, note, and working detail link.

- [ ] **Step 6: Test with one recipient unchecked**

Uncheck Carmen, submit → only Cassie receives email.
