ALL-1871 PR-2: Client-side re-validation hook with live error + summary counter updates
queued## ALL-1871 PR-2 - Frontend: Client-side re-validation on cell edit
Linear: ALL-1871 ("In-line editing of CSV data in bulk upload preview")
Branch: wilbo/all-1871-client-revalidation
Depends on: PR-1 merged (wilbo/all-1871-editable-preview-cells)
### What to build
Add a hook that re-runs client-side validation rules whenever editedCells changes, updating validationErrors + valid/invalid/total counts live. This is FRONTEND ONLY -- no server calls for address/device validation yet (that is PR-3).
### Key files
CREATE: apps/dashboard/hooks/usePreviewValidation.ts
- Input: { baseRows: PreviewRow[], editedCells: Record<number, Record<string, string>>, baseValidationErrors: ValidationError[], baseValidRows: number, baseInvalidRows: number }
- Output: { activeErrors: ValidationError[], validRows: number, invalidRows: number, mergedRows: PreviewRow[] }
- Logic:
1. Build mergedRows by applying editedCells on top of baseRows (row 0-indexed in array but 1-indexed in ValidationError.row)
2. Re-run client-side checks on only the edited rows:
- Required field check: referenceId, firstName, lastName, streetOne, city, state, postalCode must be non-empty
- Email format (basic regex: /.+@.+\..+/)
- Phone: allow empty or digits/hyphens/parens/spaces
- manufacturerSlug: if set, must be in VALID_MANUFACTURER_SLUGS (import from shared constant or copy the list)
- manufacturerSlug + systemIdentifier: both or neither
3. Merge: take baseValidationErrors, remove entries for edited rows, add new errors for those rows
4. Recompute validRows / invalidRows
- NOTE: address re-validation (geocoding) is intentionally excluded here; address fields show a pending indicator until PR-3 resolves them
- Debounce the re-validation 150ms so rapid typing doesn't thrash
EDIT: apps/dashboard/components/pages/ConnectPage/BulkUploadTab.tsx
- Import and call usePreviewValidation instead of reading validationErrors directly from previewData
- Pass activeErrors, validRows, invalidRows down to PreviewTable and the summary row counts
- The summary display ("N valid rows, M invalid rows") should now update in real time as the user edits
EDIT: apps/dashboard/components/pages/ConnectPage/BulkUpload/PreviewTable.tsx (minor)
- Accept validRows+invalidRows props if it currently reads them from previewData directly, so parent can pass live counts
### Acceptance test
- User uploads a CSV with 3 validation errors (required field missing)
- Preview shows "3 validation errors"
- User types a value into a required-field error cell
- Error count updates immediately (drops to 2) without a page reload or network request
- Valid/invalid row counts in the summary update correspondingly
- An already-valid cell edited to be empty turns red and the error count increases
### Does NOT include
- Address/geocoding re-validation (PR-3)
- manufacturerSlug server-side format checks beyond the slug whitelist
- Any data sent to backend (PR-4)
### Dependencies
- Depends on PR-1 merged (editedCells state + onCellEdit wiring already in BulkUploadTab)
### Tests
- Unit test in hooks/usePreviewValidation.test.ts: verify required-field error cleared on edit, new error added when valid cell cleared
Event Timeline
created