# Notification System Expansion Plan

## Overview
Expand the notification bell from SMS-only to a full notification system showing SMS replies, overdue callbacks, and stale hot leads.

**Status:** COMPLETE
**Created:** 2026-01-16

---

## Current State

The bell currently:
- Shows count: `smsRepliesWaiting + newSmsCount`
- On click: navigates to `/inbox`
- Only tracks SMS

## Target State

The bell will:
- Show combined count: SMS + overdue callbacks + stale hot leads
- On click: show dropdown with categorized notifications
- Each notification clickable to navigate to relevant lead

---

## Data Sources (Already Available)

The dashboard API already returns all needed data in `urgent`:

```javascript
urgent: {
  overdueCallbacks: [{ id, leadName, scheduledAt, hoursPastDue }],
  hotLeadsStale: [{ id, leadName, hoursSinceContact }],
  smsWaitingLong: [{ id, leadName, message, hoursWaiting }]
}
```

**No backend changes needed!**

---

## Implementation Steps

### Step 1: Create NotificationDropdown Component
**File:** `admin/src/components/NotificationDropdown.jsx`

Props:
- `smsNotifications: Array` - SMS replies waiting
- `callbackNotifications: Array` - Overdue callbacks
- `hotLeadNotifications: Array` - Stale hot leads
- `onItemClick: (type, item) => void` - Handle notification click
- `onClose: () => void` - Close dropdown
- `onViewAll: () => void` - Optional "View All" action

Display:
```
┌─────────────────────────────────────┐
│ NOTIFICATIONS                    ✕  │
├─────────────────────────────────────┤
│ 💬 SMS REPLIES (2)                  │
│   John D. - "Yes interested" (2h)   │
│   Sarah K. - "Call me back" (4h)    │
├─────────────────────────────────────┤
│ ⏰ OVERDUE CALLBACKS (1)            │
│   Tony M. - 2 hours overdue         │
├─────────────────────────────────────┤
│ 🔥 HOT LEADS NEED ACTION (3)        │
│   Mike T. - 52 hours since contact  │
│   James L. - 49 hours since contact │
│   +1 more                           │
└─────────────────────────────────────┘
```

Features:
- Grouped by notification type
- Shows time context (hours waiting/overdue)
- Truncates long lists with "+X more"
- Click item → navigate to lead
- Click outside → close dropdown

### Step 2: Update DashboardHeader Component
**File:** `admin/src/components/DashboardHeader.jsx`

Changes:
1. Add new props for notification data:
   - `smsNotifications`
   - `callbackNotifications`
   - `hotLeadNotifications`
   - `onNotificationItemClick`

2. Add state for dropdown visibility:
   - `isDropdownOpen: boolean`

3. Calculate total count from all three sources

4. On bell click: toggle dropdown instead of calling `onNotificationClick`

5. Render NotificationDropdown when open

6. Handle click-outside to close

### Step 3: Update Dashboard.jsx
**File:** `admin/src/pages/Dashboard.jsx`

Changes:
1. Pass notification data to DashboardHeader:
   ```jsx
   <DashboardHeader
     smsNotifications={data?.urgent?.smsWaitingLong || []}
     callbackNotifications={data?.urgent?.overdueCallbacks || []}
     hotLeadNotifications={data?.urgent?.hotLeadsStale || []}
     onNotificationItemClick={handleNotificationClick}
   />
   ```

2. Add handler for notification item clicks:
   ```jsx
   const handleNotificationClick = (type, item) => {
     if (type === 'sms') {
       navigate(`/leads/${item.leadId}`);
     } else if (type === 'callback') {
       navigate(`/leads/${item.id}`);
     } else if (type === 'hotLead') {
       navigate(`/leads/${item.id}`);
     }
   };
   ```

3. Update unreadCount calculation:
   ```jsx
   const notificationCount =
     (data?.urgent?.smsWaitingLong?.length || 0) +
     (data?.urgent?.overdueCallbacks?.length || 0) +
     (data?.urgent?.hotLeadsStale?.length || 0) +
     newSmsCount;
   ```

### Step 4: Add Click-Outside Hook (if not exists)
**File:** `admin/src/hooks/useClickOutside.js`

Simple hook for closing dropdown when clicking outside:
```javascript
export function useClickOutside(ref, callback) {
  useEffect(() => {
    function handleClick(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        callback();
      }
    }
    document.addEventListener('mousedown', handleClick);
    return () => document.removeEventListener('mousedown', handleClick);
  }, [ref, callback]);
}
```

---

## Files to Create

| File | Description |
|------|-------------|
| `admin/src/components/NotificationDropdown.jsx` | Dropdown component with grouped notifications |
| `admin/src/hooks/useClickOutside.js` | Hook for click-outside detection |

## Files to Modify

| File | Changes |
|------|---------|
| `admin/src/components/DashboardHeader.jsx` | Add dropdown toggle, new props, render dropdown |
| `admin/src/pages/Dashboard.jsx` | Pass notification data, add click handler, update count |

---

## Build Order

1. [x] Step 1: Create NotificationDropdown component
2. [x] Step 2: Create useClickOutside hook
3. [x] Step 3: Update DashboardHeader with dropdown
4. [x] Step 4: Update Dashboard.jsx to pass data

---

## Testing Checklist

- [ ] Bell shows combined count of all notification types
- [ ] Clicking bell opens dropdown (doesn't navigate)
- [ ] Dropdown shows SMS section with replies
- [ ] Dropdown shows Callbacks section with overdue items
- [ ] Dropdown shows Hot Leads section with stale leads
- [ ] Clicking notification item navigates to lead
- [ ] Clicking outside dropdown closes it
- [ ] Empty sections are hidden
- [ ] Realtime SMS updates increment count
- [ ] Mobile responsive dropdown

---

## Notes

- No backend changes required - data already available
- Reuses existing `urgent` data from dashboard API
- Keeps realtime SMS count from RealtimeContext
- Dropdown positioned below bell, right-aligned
