feat(split): add save/load templates with address-book autocomplete - #174
Conversation
|
@JohnOluB is attempting to deploy a commit to the truthixify's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@JohnOluB Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
Thanks @JohnOluB. Fix: Worth adding The template save/load itself looks like the right shape for #155. Once CI is green I will review the substance. |
|
Merged @JohnOluB. Templates with save/load/rename/duplicate, JSON export-import round trip and the contacts combobox wired into each row, which is the full scope of #155. I ran prettier and pushed the formatting commit rather than bouncing it back a second time, since it was purely mechanical. Worth adding One thing that is not yours: |
Closes #155
What this does
⚠️ Two things in the issue didn't match the codebase — flagging before review
Templates panel on /stellar/split, listed on load, with Save-as-template, Load, Rename, Duplicate, Delete.
Per-row combobox on the recipient rows (shown once a batch is validated) that suggests saved contacts as you type, plus free-text entry for addresses not yet saved.
Export/Import templates as JSON, with a conflict modal when an imported template's id already exists locally with different content.
Add recipient button to build a batch row-by-row without pasting CSV at all.
Loading a template restores the exact row set and amounts; the underlying CSV textarea stays in sync via a new serializeRowsToCsv helper, so the existing validate/submit pipeline is untouched.
"Combobox uses the ARIA pattern already established in address-book send autocomplete" — I couldn't find this anywhere (no address-book page, no combobox/listbox roles anywhere in the repo; the closest thing, AssetPicker.tsx, is a plain filtered dropdown with no ARIA combobox semantics). This PR builds a WAI-ARIA 1.2 combobox from scratch instead. Worth a careful look since it's establishing a pattern rather than reusing a proven one.
"Round-trippable with existing address-book export" — contactsStore.tsx has no export/import today. splitTemplatesStore.tsx already had a // Update the type field to match theirs exactly once you paste that code in TODO waiting on this, confirming it doesn't exist yet either. Kept that TODO as-is.
Neither blocks the feature, but the acceptance checklist as written assumes things that aren't there yet, so I didn't want to silently paper over it.
Implementation note
splitTemplatesStore.tsx already existed with CRUD (save/rename/delete/duplicate/getTemplate) and export. The only functional addition is conflict detection on import — importTemplates now takes an optional overwriteConflicts flag and returns { imported, skipped, conflicts } (was { imported, skipped }), and throws on invalid JSON instead of silently swallowing it. The import-resolution logic is pulled into a pure, exported resolveTemplateImport() so it's unit tested without a browser; everything else in the file — types, other CRUD signatures, localStorage persistence style, export envelope — is unchanged.
Testing
pnpm exec tsc --noEmit — clean
pnpm exec vitest run — 200/201 pass (new tests: splitTemplatesStore.test.ts covers CRUD + the export→import round trip via resolveTemplateImport; batchSend.test.ts covers serializeRowsToCsv + a round trip through parseCsvRows). The one failure, recoveryKit.test.ts › generates filename including meta-address prefix, is pre-existing on develop and unrelated to this change.
pnpm exec vite build — clean
pnpm format:check — clean
Not run here: pnpm test:a11y (Playwright/axe) and Storybook baseline generation for the new ContactCombobox.stories.tsx — no browser available in this environment. I reviewed the new markup carefully against tests/a11y/modals.spec.ts (which axe-scans this exact page post-validation), but please run both in CI before merging per CONTRIBUTING.md.
Files touched
src/store/splitTemplatesStore.tsx (extended), src/store/splitTemplatesStore.test.ts (new), src/components/ContactCombobox.tsx (new), src/components/ContactCombobox.stories.tsx (new), src/components/TemplateImportConflictModal.tsx (new), src/lib/stellar/batchSend.ts, src/lib/stellar/batchSend.test.ts, src/pages/StellarSplit.tsx, src/main.tsx