# LOA Task 3 — HR Communications Design
**Date:** 2026-03-30
**Scope:** Status-change notifications + ad-hoc email compose panel for LOA cases

---

## Overview

Two related features that give HR tools to communicate with employees from within the LOA portal:

1. **Status-change notifications** — automatic emails triggered whenever `leave_status` changes on a case
2. **Ad-hoc email compose panel** — HR can compose and send a free-form email to an employee (or any address) directly from `loa_edit.php`, with a log of all sent emails displayed on the case

---

## Part 1: Status-Change Notifications

### Trigger
`loa_save.php` → `handle_update()`. When `leave_status` is present in `$_POST` and the new value differs from the current DB value, fire a notification.

### Detection flow
1. Before running the UPDATE, fetch `leave_status` from `loa_form WHERE id = $id`
2. After successful UPDATE, if `$_POST['leave_status']` !== the fetched value, fetch the full case row (full_name, email, job_title, location_name, leave_category, start_date, expected_end_date, loa_id)
3. Call `send_loa_notification($new_status, $case)`

### Statuses that trigger notifications
`approved`, `denied`, `active`, `returned`, `extended`, `cancelled`

(`New` already handled; `pending` is the default insert state — no transition email needed)

### Recipients
- **Employee** — if `email` is on file (skip silently if not, log to error_log)
- **HR** — always (`hr@whitewatercw.com`)

### Email templates
Follow the existing `New` case pattern in `loa_notifications.php`:
- Each status gets a case in the `send_loa_notification()` switch
- Employee email: plain-language status update with case summary table
- HR alert: same summary table + portal link to `loa_edit.php?id=$loa_id`

---

## Part 2: Ad-hoc Email Compose Panel

### New DB table — `loa_email_log`
```sql
CREATE TABLE loa_email_log (
    id              INT AUTO_INCREMENT PRIMARY KEY,
    loa_form_id     INT NOT NULL,
    to_email        VARCHAR(255) NOT NULL,
    subject         VARCHAR(255) NOT NULL,
    body            TEXT NOT NULL,
    sent_by         VARCHAR(100) NOT NULL,
    sent_at         DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    status          ENUM('sent','failed') NOT NULL DEFAULT 'sent',
    error_message   TEXT NULL,
    INDEX idx_loa_form_id (loa_form_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

### New file — `loa_send_email.php`
- Route: `loa.php?page=loa_send_email` (POST only)
- Auth: `requireLogin()` + permission check (Edit only — same pattern as `loa_edit.php`)
- Input: `loa_id` (int), `to_email` (validated email), `subject` (string, max 255), `body` (text)
- Behavior:
  1. Validate inputs
  2. Require `loa_notifications.php`, call `send_loa_email()` with HR from/name constants
  3. INSERT into `loa_email_log` (status = sent or failed based on SendGrid response)
  4. Return JSON `{success: true}` or `{error: "message"}`
- Never throws — log failures, return `{error}` to caller

### `loa_edit.php` additions

**PHP (top of file):** Load email log rows from `loa_email_log WHERE loa_form_id = $loa_id ORDER BY sent_at DESC`

**New Section 7 — "HR Communications"** (after Section 6, before closing `</div></div>`):

*Compose panel* (canEdit only):
- **To:** text input, pre-filled with `$loa['email']`, editable
- **Subject:** text input
- **Body:** textarea (resizable)
- **Send button** → `fetch('loa.php?page=loa_send_email', {method:'POST', body:formData})`
- On success: prepend new row to log table, clear compose fields, show page message

*Email log table* (visible to all LOA users):
- Columns: Sent At | To | Subject | Sent By
- If no emails yet: italic "No emails sent." row
- New sends prepended via JS without page reload

---

## Files Changed

| File | Change |
|------|--------|
| `loa_notifications.php` | Add 6 new status cases to `send_loa_notification()` switch |
| `loa_save.php` | `handle_update()`: fetch status before UPDATE, fire notification on change |
| `loa_send_email.php` | New file — ad-hoc send endpoint |
| `loa_edit.php` | Load email log, add Section 7 (compose + log) |
| DB | `CREATE TABLE loa_email_log` |

---

## Error Handling
- Notification failures must never break case saves — same rule as `New` (try/catch, error_log only)
- Ad-hoc send failures return `{error}` JSON; JS shows page error message; row logged as `failed`
- Missing employee email on status-change: skip employee email, still send HR alert, log to error_log
