Skip to content

feat: batch payroll page using distributor contract - #20

Merged
ijeoma270 merged 11 commits into
SoroProtocol:mainfrom
nonsobethel0-dev:main
Aug 20, 2026
Merged

feat: batch payroll page using distributor contract#20
ijeoma270 merged 11 commits into
SoroProtocol:mainfrom
nonsobethel0-dev:main

Conversation

@nonsobethel0-dev

Copy link
Copy Markdown
Contributor

Closes #15

What changed

  • Added /payroll page with a 5-step flow: Mode → Recipients → Details → Review → Results
  • Mode selection: Choose between uniform rate (same for everyone) or custom amounts per person
  • Recipient input: Three methods — manual address entry, bulk CSV paste, or CSV file upload
  • CSV preview: Shows parsed addresses with valid/invalid counts before adding
  • Details step: Token selector, rate/amount fields, date range picker
  • Review screen: Total escrow cost summary, per-recipient breakdown table, confirmation dialog
  • Results screen: Success/failure status for each recipient with tx hashes
  • Distributor stubs: distribute() and distribute_custom() placeholders ready for Soroban SDK integration
  • Utilities: Escrow calculation, duration math, recipient validation with unit tests
  • UX polish: Progress bar, keyboard navigation (Escape/Enter), error summary, recipient count badge, aria-live for screen readers

Why

The distributor contract lets teams pay many contributors in one transaction. There was no UI for it — this is the primary use case for teams on the protocol.

How to test

  1. Run npm run dev and navigate to /payroll
  2. Connect a Freighter wallet
  3. Select Uniform or Custom mode
  4. Add recipients (manual, paste CSV, or upload file)
  5. Set token, rate/amount, and date range
  6. Review the total escrow cost breakdown
  7. Confirm and submit

Notes

  • Contract calls are stubbed with simulated results (same pattern as /create page)
  • CSS Modules matching existing design tokens (no new dependencies)
  • Responsive on mobile (grid collapses, rows wrap)

@ijeoma270

Copy link
Copy Markdown
Contributor

the multi-step flow is well done, CSV parsing and the preview step are nice touches. a few things though:

you built usePayrollForm but the page doesn't use it — page.tsx has its own inline state management, validation, and escrow logic that duplicates what the hook does. same with useKeyboardNav and useLocalStorage — both defined, neither imported anywhere. feels like you extracted these hooks but forgot to wire them in.

ConfirmDialog component exists but it's never shown. the submit button goes straight to handleSubmit with no confirmation modal. for a batch payment flow that's sending real money, that confirmation step is kind of important.

there's also a second distributor service at src/services/distributor.ts — PR #19 already added one at src/lib/contracts/distributor.ts. two different files doing the same thing. whichever one lands second will need to reconcile with the first.

calcEscrow in src/lib/payroll.ts is exported but never called — the review step calculates escrow inline instead. pick one place for that logic.

the address regex is ^G[A-Z2-7]{55}$ which is fine for mainnet but testnet addresses start with different characters. not a blocker for now but worth noting.

overall the page structure and UX flow are solid. just needs the dead code cleaned up and the confirm dialog actually wired in before submission.

…tep shell

Set up the /payroll route with TypeScript types for payroll state,
recipient parsing utilities, CSS module matching existing design tokens,
and a basic page component with step progress indicator.
Add ModeStep (uniform vs custom), RecipientsStep (manual/paste/upload),
DetailsStep (token, rate, dates), ReviewStep (cost breakdown table),
and ResultsStep (success/fail per recipient). Wire into the main page
with back/next navigation, validation, and simulated submission.
…submission

Add distributor.ts with distribute() and distribute_custom() placeholders
for Soroban SDK integration. Wire the payroll page to call these on submit.
Add Payroll link to the navigation bar.
Centralize payroll state, validation, and escrow calculation into a
reusable hook. Keeps the page component focused on step navigation.
Show a modal with total escrow cost and recipient count before the
user confirms. Prevents accidental submissions.
Extract escrow cost, duration, and recipient validation logic into
src/lib/payroll.ts with unit tests covering edge cases.
Show a preview of parsed addresses with valid/invalid counts before
the user confirms adding them. Prevents accidentally adding bad data.
…ation

ErrorSummary shows validation issues inline. RecipientBadge displays the
count in step labels. useKeyboardNav adds Escape-to-go-back and
Enter-to-advance shortcuts.
Generic useState wrapper that syncs to localStorage, enabling payroll
form data to survive page refreshes.
Announce step changes to assistive technology so users following the
multi-step flow know which step they are on.
… remove duplicates

- Wire usePayrollForm hook into page, replacing inline state/validation
- Wire useKeyboardNav for Escape/Enter shortcuts
- Show ConfirmDialog before batch submission
- Remove duplicate src/services/distributor.ts, use src/lib/contracts/distributor.ts
- Use calcEscrow and calcUniformPerRecipient from src/lib/payroll.ts in ReviewStep
@nonsobethel0-dev

Copy link
Copy Markdown
Contributor Author

Thanks for the review — all issues addressed:

  1. Hooks wired in: usePayrollForm now manages all state/validation/escrow. useKeyboardNav added for Escape/Enter shortcuts. Removed useLocalStorage since it wasn't needed.
  2. ConfirmDialog: Now shown when user clicks "Review & Submit" on the review step — blocks until they confirm or cancel.
  3. Duplicate distributor removed: Deleted src/services/distributor.ts, using the one from PR feat: build full Soroban contract client service layer #19 at src/lib/contracts/distributor.ts.
  4. calcEscrow: ReviewStep now uses calcEscrow and calcUniformPerRecipient from src/lib/payroll.ts instead of inline logic.

@ijeoma270

Copy link
Copy Markdown
Contributor

LGTM, thanks for contribuing

@ijeoma270
ijeoma270 merged commit 68eea96 into SoroProtocol:main Aug 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: batch payroll page using distributor contract

2 participants