# Customers CRM - Developer Guide

## Overview

The Customers page is a single-page CRM interface for managing pest control customers. It supports light and dark themes, card and table views, town-based filtering, search, bulk actions, and a new lead intake form with voice fill and address autocomplete.

## File Structure

```
Customers/
├── customers.html          # Page structure, header bar, card/table views, new lead modal
├── css/styles.css          # Custom CSS (animations, theme toggle, star ratings, voice fill)
├── js/tailwind-config.js   # Tailwind dark mode + custom color/shadow tokens
├── js/app.js               # All application logic (745 lines)
└── DEVELOPER_GUIDE.md      # This file
```

## Features

### Header Bar
- Warm stone (`#938c87`) background with translucent white controls
- Search input filters customers by name, town, email, phone, or address
- Status filter dropdown: All, Current, Past Due, VIP
- Bulk action dropdown: Email, Text, Delete (operates on selected cards)
- +New button opens the new lead modal
- Light/dark theme toggle (removable)

### Town Filter Pills
- Horizontal scrollable row of town buttons below the header
- Multi-select: click to toggle, filters the customer list
- "Clear" button resets all town filters

### Card View
- Each card shows: name, town, email, phone, address (linked to Google Maps), balance, price
- Selectable via checkbox for bulk actions
- Click card body to open customer profile (URL currently stubbed)
- Paid customers show green checkmark; past-due show red balance

### Table View
- Same data in a sortable table layout
- Toggle between card and table view via header buttons

### New Lead Modal
- Two-step form: contact info first, then save as Lead or Customer
- **Voice Fill**: Uses Web Speech Recognition API to fill form fields by voice; falls back to iPad dictation for unsupported browsers
- **Phone formatting**: Auto-formats to `(xxx) xxx-xxxx` as the user types
- **Email normalization**: Converts spoken "at" to `@`, "dot com" to `.com`, etc.
- **Name/city capitalization**: Auto-capitalizes first letter of each word
- **Star rating**: 1-5 first impression rating
- **Address autocomplete**: Google Places API fills address, city, state, zip
- Add/remove multiple phone and email fields

### Theme System
- Light mode: warm cream background (`#f2f1eb`), forest green (`#3b8030`) accents
- Dark mode: dark background (`#0f1115`), blue accents
- Toggle button in the header (built to be easily removable)

---

## Database & API Connection Points

All connection points are in `js/app.js` and marked with `// DATABASE CONNECTION POINT` or `// API CONNECTION POINT` comments.

| # | Purpose | File | Line | Current Behavior | Replace With |
|---|---------|------|------|-----------------|--------------|
| 1 | **Customer data source** | `js/app.js` | **42-84** | Static array of 40 customer objects | `fetch('/api/customers')` or database query |
| 2 | **Customer profile link** | `js/app.js` | **185** | Stubbed URL `/crm/customer/{id}` | Your actual routing/profile page URL |
| 3 | **Bulk actions** | `js/app.js` | **311-332** | `alert()` / `confirm()` dialogs | `POST /api/bulk-action` with action type and customer IDs |
| 4 | **Google Places API** | `js/app.js` | **625-654** | Google Maps Places Autocomplete (active) | Replace API key in `customers.html` `<script>` tag for production |
| 5 | **Save new customer** | `js/app.js` | **697-733** | `customers.push()` to local array | `POST /api/customers` with the new customer object |

### Connection Point Details

#### 1. Customer Data Source (line 42)
```js
// DATABASE CONNECTION POINT: Replace this static array with an API fetch.
// Example: const customers = await fetch('/api/customers').then(r => r.json());
const customers = [ ... ];
```
Each customer object has: `id`, `name`, `town`, `email`, `phone`, `address`, `balance`, `price`, and optionally `vip: true`.

#### 2. Customer Profile Link (line 185)
```js
// DATABASE CONNECTION POINT: Replace with dynamic profile URL from your routing system.
const profileUrl = `/crm/customer/${c.id}`;
```

#### 3. Bulk Actions (line 311)
```js
// DATABASE CONNECTION POINT: Replace alert/confirm with actual API calls for bulk actions.
// Example: await fetch('/api/bulk-action', { method: 'POST', body: JSON.stringify({ action, customerIds }) });
```
Actions: `email-all`, `text-all`, `delete`

#### 4. Google Places API (line 625)
```js
// API CONNECTION POINT: Google Maps Places API for address lookup.
// Key is loaded via script tag in HTML. Replace key in HTML <script> tag for production.
```
The API key is in `customers.html` in the Google Maps `<script>` tag. The autocomplete fills: address line, city, state, and zip.

#### 5. Save New Customer (line 697)
```js
// DATABASE CONNECTION POINT: Replace customers.push() with an API POST to save the new customer.
// Example: await fetch('/api/customers', { method: 'POST', body: JSON.stringify(newCustomer) });
```
The `saveNewCustomer(stage)` function collects all form fields and creates a customer object with a `stage` property ("lead" or "customer").

---

## External Dependencies

| Library | Version | Purpose |
|---------|---------|---------|
| Tailwind CSS | 3.4.16 (CDN) | Utility-first CSS framework |
| Lucide Icons | latest (CDN) | SVG icon library |
| Google Maps Places API | v3 | Address autocomplete |

## Key JS Architecture Notes

- All JS is wrapped in an IIFE to avoid global scope pollution
- Functions needed by `onclick` handlers in HTML are exported via `window.*` (lines 726-738)
- Voice fill uses the Web Speech Recognition API with an iPad dictation fallback
- The `state` object (line 5) holds all UI state: selected towns, search query, selected card IDs, status filter, view mode, voice mode
