ALL-1871 PR-3: Address re-geocoding validation on address cell edits
queued## ALL-1871 PR-3 - Frontend: Address re-geocoding on edit (debounced)
Linear: ALL-1871 ("In-line editing of CSV data in bulk upload preview")
Branch: wilbo/all-1871-address-revalidation
Depends on: PR-2 merged (usePreviewValidation hook)
### What to build
When address fields (streetOne, streetTwo, city, state, postalCode, country) are edited, re-run the backend geocoding/address validation for those rows via GraphQL, then feed the result back into the live validation state.
### GraphQL available
The schema already has validateAddresses (batch) -- check apps/dashboard/lib/@generated/graphql.ts for the exact query shape:
- Query: `validateAddresses(addresses: [AddressInput!]!): [AddressValidationBatchResult!]!`
(search graphql.ts for `validateAddresses` to find input/return types)
- This is the same endpoint the backend validation service uses internally
- It hits Mapbox so MUST be debounced (500ms per Linear issue spec)
### Key files
CREATE: apps/dashboard/hooks/useAddressRevalidation.ts
- Input: mergedRows (from usePreviewValidation), editedCells, activeErrors
- Tracks which row indices have had address fields edited since last geocode
- On change, waits 500ms (debounce), then calls validateAddresses for dirty address rows
- Returns: { addressErrors: ValidationError[], pendingRows: Set<number> }
- pendingRows: row indices awaiting geocoding result (UI can show a spinner on those address cells)
- addressErrors: validation errors for address fields from geocoder response
EDIT: apps/dashboard/hooks/usePreviewValidation.ts
- Accept addressErrors as an additional input and merge them with client-side errors
- Address field errors in activeErrors should be replaced by addressErrors for the relevant rows
EDIT: apps/dashboard/components/pages/ConnectPage/BulkUpload/EditableCell.tsx (from PR-1)
- Accept optional `isPending?: boolean` prop
- When true, show a small spinner/loading indicator instead of the error/normal state so user knows geocoding is in flight
EDIT: apps/dashboard/components/pages/ConnectPage/BulkUploadTab.tsx
- Wire up useAddressRevalidation, pass pendingRows down to PreviewTable -> EditableCell
### Address fields to watch
streetOne, streetTwo, city, state, postalCode, country
Any edit to any of these for a given row marks that row as needing re-geocoding.
### Rate limit protection
- 500ms debounce window after last keystroke
- Batch: collect all dirty address rows and geocode in one validateAddresses call
- Do NOT geocode on every keypress
### Acceptance test
- User edits a street address cell
- Address cells in that row briefly show a pending/loading indicator
- After ~500ms, if valid geocode, previous address error clears
- If invalid address, cells show red border with geocoder error message
- Fixing a previously-invalid address removes the error from the error panel
### Does NOT include
- Sending edited rows to backend import endpoint (PR-4)
- Re-validating device/manufacturer fields server-side
### Dependencies
- Depends on PR-2 merged (usePreviewValidation hook in place)
### Gotcha
The validateAddresses GQL query might not be exposed in the apollo client hooks yet -- check apps/dashboard/lib/gql/queries/ for it. If not present, create a new .graphql file and run codegen (pnpm codegen from apps/dashboard).
Event Timeline
created