Skip to content

feat(receipt): TASK-24141 record which receipt action users tap - #3897

Merged
abalinda merged 1 commit into
devfrom
feat/TASK-24141-receipt-action-events
Oct 31, 2026
Merged

abalinda merged 1 commit into
devfrom
feat/TASK-24141-receipt-action-events

Conversation

@abalinda

Copy link
Copy Markdown
Contributor

Summary

#3896 made Share receipt (the link) the primary on every receipt and moved Split this bill to More actions. Neither tap was measured: autocapture is off in production, and the only proxy for Split was requests created with the prefilled "Bill split for …" comment, about 1 in 100 eligible QR and card receipts, by roughly 10 people a week. This PR records every tap so the primary can be judged on data in four weeks.

One event, receipt_action_tapped, with three properties:

Property Values
action share_link, share_pdf, download_pdf, split
placement primary, more_actions, qr_success
kind the entry's wire kind (DIRECT_TRANSFER, QR_PAY, CARD_SPEND_CLEAR, …)

The tap is recorded, not its outcome: a share sheet the user closes still says they wanted to share. ShareButton gets an onClick that runs on the tap, before the share starts, for that reason.

Task: TASK-24141 Share receipt links for every transaction type. Follow-ups of the receipt work: TASK-24263.

Where it fires

  • ReceiptActions.tsx: the link primary, the Split primary, the PDF share primary, and the More actions rows Split, Share receipt (PDF), Download receipt (PDF).
  • QrPaySuccessView.tsx: Split this bill on the QR payment success screen (placement: qr_success), once per screen even on a double tap.
  • receipt-action-analytics.ts holds the one trackReceiptAction helper and its two types.

Risks

  • Analytics only; no behaviour changes. Production is the only environment that sends events (ui#3767).
  • Nothing personal in the properties: an action name, a placement name and an intent kind.

Tests

  • ReceiptActions.receipt-routing.test.tsx: one event per control, with the expected action, placement and kind, in the drawer's four shapes.
  • QrPaySuccessView.test.tsx: the success-screen Split records one tap, also on a double tap.
  • ShareButton.test.tsx: onClick runs on the tap, before the share, also when the share then fails.
  • Local: typecheck clean, prettier clean, the six receipt, QR and ShareButton suites green (45 tests). The full suite and the build run in parallel with CI; results in the readiness report.

Reading the data

In PostHog, a trends insight on receipt_action_tapped broken down by action, filtered by placement, answers "share link vs split" per week; add kind to compare QR and card receipts with the rest.

Screenshots: N/A (no visible change)

🤖 Generated with Claude Code

Share receipt (the link) became the primary on every receipt and Split this
bill moved to More actions (#3896). Neither tap was measured: autocapture is
off in production, and the only proxy was requests with a prefilled split
comment, about 1 in 100 eligible receipts. One event, receipt_action_tapped
with action, placement and kind, now records every tap on share link, share
PDF, download PDF and split, in the drawer and on the QR success screen, so
the primary can be judged on data in four weeks.

ShareButton takes an onClick that runs on the tap, before the share, because
a share sheet the user closes still says they wanted to share.
@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
peanut-wallet Ready Ready Preview Oct 31, 2026 9:20am UTC

Request Review

@notion-workspace

Copy link
Copy Markdown

@abalinda

Copy link
Copy Markdown
Contributor Author

/chip review

@github-actions

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 10582.78 → 10585.3 (+2.52)
Findings: +1 net (+15 new, -14 resolved)

🆕 New findings (15)

  • critical complexity — src/components/TransactionDetails/ReceiptActions.tsx — CC 123, MI 58.99, SLOC 280
  • critical method-complexity — src/components/TransactionDetails/ReceiptActions.tsx:60 — ReceiptActions CC 78 SLOC 178
  • critical complexity — src/constants/analytics.consts.ts — CC 1, MI 29.03, SLOC 241
  • high hotspot — src/constants/analytics.consts.ts — 101 commits, +446/-99 lines since 6 months ago
  • high complexity — src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx — CC 45, MI 57.56, SLOC 138
  • medium high-mdd — src/components/TransactionDetails/ReceiptActions.tsx:60 — ReceiptActions: MDD 161.9 (uses across many lines from declarations)
  • medium high-mdd — src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:33 — QrPaySuccessView: MDD 88.5 (uses across many lines from declarations)
  • medium high-dlt — src/components/TransactionDetails/ReceiptActions.tsx:60 — ReceiptActions: DLT 51 (calls 51 distinct functions — high context load)
  • medium high-dlt — src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:33 — QrPaySuccessView: DLT 30 (calls 30 distinct functions — high context load)
  • medium method-complexity — src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:33 — QrPaySuccessView CC 23 SLOC 92
  • medium react-effect-derives-state — src/components/TransactionDetails/ReceiptActions.tsx:137 — small useEffect that only sets state from deps
  • medium react-effect-derives-state — src/components/TransactionDetails/ReceiptActions.tsx:142 — small useEffect that only sets state from deps
  • low high-mdd — src/components/Global/ShareButton/index.tsx:22 — ShareButton: MDD 12.0 (uses across many lines from declarations)
  • low missing-return-type — src/components/TransactionDetails/ReceiptActions.tsx:60 — ReceiptActions: exported fn missing return type annotation
  • low missing-return-type — src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:33 — QrPaySuccessView: exported fn missing return type annotation

✅ Resolved (14)

  • src/components/TransactionDetails/ReceiptActions.tsx — CC 120, MI 58.13, SLOC 269
  • src/components/TransactionDetails/ReceiptActions.tsx:59 — ReceiptActions CC 78 SLOC 174
  • src/constants/analytics.consts.ts — CC 1, MI 29.07, SLOC 240
  • src/constants/analytics.consts.ts — 100 commits, +438/-99 lines since 6 months ago
  • src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx — CC 45, MI 57.62, SLOC 137
  • src/components/TransactionDetails/ReceiptActions.tsx:59 — ReceiptActions: MDD 157.5 (uses across many lines from declarations)
  • src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:32 — QrPaySuccessView: MDD 88.3 (uses across many lines from declarations)
  • src/components/TransactionDetails/ReceiptActions.tsx:59 — ReceiptActions: DLT 49 (calls 49 distinct functions — high context load)
  • src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:32 — QrPaySuccessView CC 23 SLOC 92
  • src/components/TransactionDetails/ReceiptActions.tsx:136 — small useEffect that only sets state from deps
  • src/components/TransactionDetails/ReceiptActions.tsx:141 — small useEffect that only sets state from deps
  • src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:32 — QrPaySuccessView: DLT 29 (calls 29 distinct functions — high context load)
  • src/components/TransactionDetails/ReceiptActions.tsx:59 — ReceiptActions: exported fn missing return type annotation
  • src/features/payments/flows/qr-pay/views/QrPaySuccessView.tsx:32 — QrPaySuccessView: exported fn missing return type annotation

📈 Painscore deltas (top movers)

File Before After Δ
src/components/TransactionDetails/receipt-action-analytics.ts 0.0 2.1 +2.1

@chip-peanut-bot chip-peanut-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip review — no blocking findings — this is not an approval

No findings.

Checked clean

  • Confirmed the detached worktree head and exact dev merge base; reviewed the full eight-file diff.
  • Checked receipt-action placement and kind against rendered primary, overflow, and QR-success controls, including disabled actions and the single-navigation guard.
  • Checked ShareButton tap callback ordering against the share hook and its failure-path test; existing share behavior remains intact.
  • Checked the analytics capture configuration and design rulebook; the added event carries only action, placement, and wire kind.
  • At review time, typecheck, eslint, format, ds-lint, screen tests, and provenance checks passed; unit and several unrelated jobs were still in progress.

Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.

Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Copy check by claude-haiku-5-5: 0 finding(s), titled "Copy now wrong". Every quoted passage was checked against the file.

Exact head: 43362ec20807 · Context: repo, design, lexicon · Took 5m

@github-actions

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • ✅ unit: 14774 ran, 0 failed, 0 skipped, 4.6m

📊 Coverage (unit)

metric %
statements 86.3%
branches 78.0%
functions 81.4%
lines 87.6%
⏱ 10 slowest test cases
time test
🐢 9.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Network failure keeps loading while retries remain, then shows the generic error
🐢 5.5s scripts/__tests__/signup-attribution-paths.test.ts › includes newly published articles and locale fallbacks without editing the manifest
🐢 5.2s scripts/__tests__/indexable-urls.test.ts › excludes missing locale files, drafts, redirects, and retired pages from crawl and submission lists
4.0s src/features/setup/__tests__/useSignupPasskey.test.tsx › opens the help drawer for NotReadableError and retries from it with one more ceremony
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › User KYC not approved fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_SOURCE_OVER_MONTHLY_CAP fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_MERCHANT_VOLUME_NEAR_CAP fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_MERCHANT_RECENT_REFUND fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › routes the KYC rejection on its wire code, and does not retry it
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › a refused idempotency key tells the user to scan again, not to contact support
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@abalinda
abalinda marked this pull request as ready for review October 31, 2026 09:41
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

English

Open screen library dashboard

After merge: 7219640 → e6b32f1. Reviewable capture in English; newly registered states are marked in the report.

@abalinda
abalinda merged commit e6b32f1 into dev Oct 31, 2026
51 checks passed

This branch was successfully deployed

1 active deployment
Preview — 43362ec2 Deployed Oct 31, 2026 by vercel[bot]
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.

1 participant