# CRH HMIS — Design System Adoption Guide

A practical, low-risk plan to replace page-specific styling with shared, reusable parts. **No business logic changes** — every step here is presentation-layer only and reversible.

## What's in this delivery
| File | Purpose |
|---|---|
| `public/css/crh-design-system.css` | Tokens (type/colour/spacing/radius) + component classes |
| `public/js/crh-postjson.js` | One AJAX helper that surfaces real errors |
| `resources/views/components/ui/*.blade.php` | `<x-ui.*>` components |
| `docs/CRH-HMIS-QA-Audit.md` | The full audit |

## Step 0 — Wire it up (once)
In `resources/views/layouts/app.blade.php`, inside `<head>`, **after** the existing `<style>` block:
```blade
<link rel="stylesheet" href="{{ asset('css/crh-design-system.css') }}">
```
Before `</body>`:
```blade
<script src="{{ asset('js/crh-postjson.js') }}"></script>
```
Confirm a CSRF meta tag exists in `<head>` (the helper reads it):
```blade
<meta name="csrf-token" content="{{ csrf_token() }}">
```
Because all new classes are namespaced `crh-`, **nothing changes visually until you start using them.** Existing `.btn-*`, `.table-*`, `.form-*` keep working untouched.

## Step 1 — Drop the dev Tailwind CDN (finding SW-1)
Once the design-system CSS covers your needs, remove `<script src="https://cdn.tailwindcss.com"></script>` from the layout. If a few raw Tailwind utilities are still needed short-term, leave it for now and revisit — but it should not remain in production long-term.

## Step 2 — Migrate worst-first
Order by measured styling debt: **billing → visits → pharmacy → corporate → hr → lab/imaging.** `finance`, `patients`, `admin`, `crm`, `feedback` are already clean.

### Mechanical replacements (behaviour-preserving)
| Old (inline / ad-hoc) | New (component) |
|---|---|
| `<button class="btn-success" style="padding:4px 10px;font-size:11.5px">Save</button>` | `<x-ui.button variant="success" size="sm">Save</x-ui.button>` |
| `<button class="btn-primary" style="padding:7px 14px">Save Changes</button>` | `<x-ui.button variant="primary">Save Changes</x-ui.button>` |
| `<table>…<th style="…">…<td style="…">…</table>` | `<x-ui.table :headers="['Date','Patient','Amount']"> …<tr>…<td>…</td></tr>… </x-ui.table>` |
| `<label style="…">Amount</label><input class="form-input" …>` | `<x-ui.input label="Amount" name="amount" required />` |
| `<select class="form-input">…</select>` | `<x-ui.select label="Method" name="method" :options="$methods" />` |
| `<span style="font-size:9px;…">Paid</span>` | `<x-ui.badge tone="green">Paid</x-ui.badge>` |
| any inline `font-size:NNpx` | delete it — the scale/component governs size |

### Component cheat-sheet
```blade
<x-ui.page-header title="Payments" subtitle="Today's shift">
    <x-slot:actions>
        <x-ui.button variant="primary" href="{{ route('billing.payment') }}">+ Record</x-ui.button>
    </x-slot:actions>
</x-ui.page-header>

<x-ui.card title="Outstanding invoices">
    <x-ui.table :headers="['Invoice','Patient','Balance','']">
        @forelse($invoices as $inv)
            <tr>
                <td>{{ $inv->invoice_number }}</td>
                <td>{{ $inv->patient->full_name }}</td>
                <td>KES {{ number_format($inv->balance) }}</td>
                <td><x-ui.button size="sm" variant="ghost" href="#">View</x-ui.button></td>
            </tr>
        @empty
            <x-slot:emptyState><tr><td colspan="4" class="crh-table__empty">No invoices.</td></tr></x-slot:emptyState>
        @endforelse
    </x-ui.table>
</x-ui.card>

<x-ui.modal id="payModal" title="Record payment">
    <x-ui.input label="Amount" name="amount" type="number" required />
    <x-ui.select label="Method" name="payment_method" :options="['cash'=>'Cash','mpesa'=>'M-Pesa']" required />
    <x-slot:footer>
        <x-ui.button variant="ghost" onclick="document.getElementById('payModal').setAttribute('hidden','')">Cancel</x-ui.button>
        <x-ui.button variant="success" onclick="submitPayment()">Save</x-ui.button>
    </x-slot:footer>
</x-ui.modal>
```

### Switch AJAX to the helper (findings SW-6 / SW-7)
```js
// Before — swallows the real reason:
fetch(url,{method:'POST',body:fd}).then(r=>r.json()).then(d=>{
  if(d.success) location.reload(); else alert('Failed to save. Please try again.');
});

// After — shows the real reason (lock / validation / session):
try { await postJson(url, fd); location.reload(); }
catch (e) { alert(e.message); }
```
Priority files (currently no `.catch`): `crm/follow-ups`, `corporate/referrals/*`, `corporate/accounts/show`, `pharmacy/drugs-categorize`, `pharmacy/drugs-bulk-edit`.

## Step 3 — Deploy (cPanel ZIP, no SSH)
1. ZIP the four locations preserving paths: `public/css/`, `public/js/`, `resources/views/components/ui/`, the edited `layouts/app.blade.php`.
2. Upload/extract over `public_html`.
3. Blade views recompile automatically on file-change; no artisan needed. (If a component ever appears not to update, it's view cache — clearing `storage/framework/views/*.php` forces recompile.)

## Definition of done (per module)
- [ ] No inline `font-size` remains
- [ ] All buttons via `<x-ui.button>`
- [ ] All tables via `<x-ui.table>` (mobile-scroll wrapped)
- [ ] All form fields via `<x-ui.input>` / `<x-ui.select>`
- [ ] All AJAX via `postJson()`
- [ ] All create/update/delete/void/approve call `AuditService::log` (see audit SW-4)

## How to track progress
Re-run the inline-style count after each module:
```
grep -roh "style=" --include=*.blade.php resources/views/<module> | wc -l
```
Target: total project inline `style=` trending from **2,282 → under 300**.
