# Dashboard Metric Cards

The ShopProQuote dashboard (`dashboard.html` / `dashboard.js`) has a set of Quick Metric cards that display live counts from the repair orders, appointments, tasks, and quotes collections.

## Architecture

### HTML — Card Structure

Cards live in a Tailwind grid inside `<!-- Quick Metrics -->`:

```html
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-6 mb-8">
```

Each card follows this exact template:

```html
<!-- Card Label -->
<div class="metric-card rounded-xl p-6 shadow-lg">
    <div class="flex items-center justify-between mb-4">
        <div class="p-2 bg-COLOR-100 dark:bg-COLOR-900 rounded-lg">
            <!-- SVG icon matching the metric theme -->
            <svg class="w-6 h-6 text-COLOR-600 dark:text-COLOR-400" ...>...</svg>
        </div>
        <span id="UNIQUE-ID-count" class="text-3xl font-bold text-gray-900 dark:text-white">0</span>
    </div>
    <h3 class="text-sm font-medium text-gray-600 dark:text-gray-400 mb-2">Card Title</h3>
    <div class="text-xs text-gray-500 dark:text-gray-500" id="UNIQUE-ID-breakdown">
        <!-- Optional sub-items with status-indicator spans -->
        <span class="status-indicator status-COLOR"></span>Status label
    </div>
</div>
```

**Key:**
- Each card gets a unique `id` on its count `<span>` (e.g., `parts-on-order-count`, `ready-for-pickup-count`)
- Color variants: `bg-{color}-100`, `text-{color}-600` (light) / `bg-{color}-900`, `text-{color}-400` (dark)
- Status indicators use the existing class system: `status-overdue` (red), `status-warning` (amber), `status-good` (green), `status-info` (blue)
- When adding cards, count the total. If > 4, bump `lg:grid-cols-4` to `lg:grid-cols-6` (or `lg:grid-cols-3` for two rows of 3).

### JS — Data Population (`renderMetrics()`)

The `renderMetrics()` function in `dashboard.js` (~line 1528) populates all metric cards. It's called from `renderDashboard()` on every data refresh.

**Pattern for adding a new card:**

```js
// 1. Compute the value from dashboardData
const myMetric = dashboardData.repairOrders.filter(ro =>
    (ro.status || '').toLowerCase() === 'my-status-value'
).length;

// 2. Log for debugging
log('My Metric count:', myMetric);

// 3. Update DOM with null-safe access
const myMetricEl = document.getElementById('my-metric-count');
if (myMetricEl) myMetricEl.textContent = myMetric;
```

**Available data sources for filtering:**
- `dashboardData.repairOrders` — objects with `.status` (string), `.writeupTime` (Date), `.promisedTime` (Date), `.customerName`
- `dashboardData.appointments` — objects with `.status`, `.appointmentDateTime` (Date), `.customerName`
**Available data sources for filtering:**
- `dashboardData.repairOrders` — objects with `.workStatus` (string: diagnosing/in-progress/waiting-for-approval/waiting-for-parts/waiting-for-pickup/completed), `.status` (string: waiter/drop-off — customer service status, NOT work progress), `.writeupTime` (Date), `.promisedTime` (Date), `.customerName`

**CRITICAL: `ro.status` ≠ `ro.workStatus`**
- `ro.status` = customer service status (`waiter`, `drop-off`) — used for the red/blue service badge on RO cards
- `ro.workStatus` = work progress status (`diagnosing`, `in-progress`, `waiting-for-approval`, `waiting-for-parts`, `waiting-for-pickup`, `completed`) — used for work progress badges and ALL completion/dashboard filtering logic

**NEVER filter by `ro.status === 'completed'`** — it will always match nothing because `status` only stores `waiter`/`drop-off`. Always use `ro.workStatus === 'completed'`.

**Common repair order workStatus values used in filters:**
- `'diagnosing'`, `'in-progress'`, `'waiting-for-approval'`, `'waiting-for-parts'`, `'waiting-for-pickup'`, `'completed'`

### Click Handlers

Metric cards can optionally be made clickable. Follow the existing pattern in `addMetricClickHandlers()` (~line 1888):

```js
const myCard = document.querySelector('#my-metric-count')?.closest('.metric-card');
if (myCard) {
    myCard.style.cursor = 'pointer';
    myCard.addEventListener('click', () => {
        window.location.href = 'target-page.html';
    });
}
```

## Adding a New Metric Card — Full Recipe

1. **HTML**: Add the card `<div>` inside the Quick Metrics grid, following the template above. Ensure the count `<span>` has a unique ID.
2. **Grid**: If total cards exceed the current `lg:grid-cols-N` value, bump it.
3. **JS**: In `renderMetrics()`, after the existing quote section (~line 1674), add filter logic + DOM update.
4. **Click handler (optional)**: If the card should navigate somewhere, add it in `addMetricClickHandlers()`.
5. **Verify**: The card will populate automatically on next data refresh (periodic auto-refresh + real-time PocketBase subscriptions).
