lukia lab

React island · seeded data · inline SVG

Transaction explorer

A merchant dashboard over an invented ledger: filter it, sort it, watch payments arrive and settle. Every figure on it comes from a pure function with tests over it, and the charts are rectangles this repo measured rather than a library’s idea of a bar.

This is the piece closest to what I do for a living. The interesting part of a payments screen is never the chart — it is holding money as integers, refusing to net a refund against a sale, and knowing that a settled transaction does not go backwards.

The dashboard

New payments arrive every 2.5 seconds.

Showing 60 of 60 transactions.

Payments
60
Gross
R 16 919,16
Refunded
R 1 004,23
Success rate
80%
Payments over time
Payments over time
IntervalPayments
09:595
10:195
10:395
10:594
11:196
11:395
11:594
12:195
12:396
12:595
13:195
13:395
Payments by status
Payments by status
StatusPayments
Authorised12
Settled36
Refunded3
Failed6
Reversed3
Transactions, 60 of 60, sorted by Time descending.
ReferenceMethod
13:59INV-4100Kloof Street RoasteryEFTR 329,00Settled
13:55INV-4101Table Bay CyclesInstant EFTR 432,35Settled
13:51INV-4102Sandton DentalEFTR 472,45Settled
13:46INV-4103Halyard StudioCardR 302,41Settled
13:43INV-4104Umhlanga YogaCardR 35,37Authorised
13:38INV-4105Halyard StudioInstant EFTR 231,64Settled
13:35INV-4106Muizenberg Surf CoEFTR 31,61Settled
13:31INV-4107Kloof Street RoasteryCapitec PayR 229,56Refunded
13:26INV-4108Kloof Street RoasteryCardR 1 808,07Settled
13:23INV-4109Ubuntu BooksEFTR 267,58Authorised
13:18INV-4110Kloof Street RoasteryCardR 313,79Settled
13:14INV-4111Muizenberg Surf CoCardR 361,34Authorised
13:11INV-4112Sandton DentalCapitec PayR 376,97FailedIssuer declined
13:07INV-4113Sandton DentalCardR 307,31FailedInsufficient funds
13:03INV-4114Sandton DentalInstant EFTR 243,28Settled
12:58INV-4115Kloof Street RoasteryInstant EFTR 1 126,50Settled
12:55INV-4116Sandton DentalCapitec PayR 469,01Authorised
12:51INV-4117Halyard StudioEFTR 119,96Settled
12:46INV-4118Karoo ProvisionsEFTR 116,33Failed3-D Secure abandoned
12:43INV-4119Muizenberg Surf CoCardR 235,71Settled
12:39INV-4120Sandton DentalCardR 116,65Authorised
12:34INV-4121Sandton DentalEFTR 378,07Settled
12:31INV-4122Halyard StudioCapitec PayR 468,21Settled
12:26INV-4123Sandton DentalEFTR 148,04Settled
12:23INV-4124Table Bay CyclesCardR 382,40ReversedIssuer declined
12:19INV-4125Ubuntu BooksCardR 151,59Settled
12:14INV-4126Sandton DentalCardR 117,51Settled
12:11INV-4127Sandton DentalEFTR 402,74Authorised
12:06INV-4128Kloof Street RoasteryCapitec PayR 395,17Refunded
12:03INV-4129Halyard StudioCardR 1 521,76Settled
11:58INV-4130Table Bay CyclesEFTR 218,48Settled
11:55INV-4131Kloof Street RoasteryCardR 102,86Settled
11:51INV-4132Muizenberg Surf CoCapitec PayR 106,75Settled
11:46INV-4133Table Bay CyclesCapitec PayR 379,50Refunded
11:42INV-4134Umhlanga YogaCardR 96,16Settled
11:38INV-4135Karoo ProvisionsCapitec PayR 477,78Settled
11:34INV-4136Umhlanga YogaEFTR 44,59FailedTimed out at the bank
11:31INV-4137Table Bay CyclesEFTR 181,63Reversed3-D Secure abandoned
11:27INV-4138Table Bay CyclesInstant EFTR 314,23Settled
11:22INV-4139Sandton DentalCapitec PayR 184,31Settled
11:19INV-4140Karoo ProvisionsInstant EFTR 214,02Settled
11:14INV-4141Halyard StudioEFTR 338,00Settled
11:11INV-4142Umhlanga YogaCardR 275,56Settled
11:06INV-4143Muizenberg Surf CoInstant EFTR 400,86Authorised
11:02INV-4144Sandton DentalCardR 355,68Settled
10:58INV-4145Kloof Street RoasteryEFTR 220,50Authorised
10:55INV-4146Halyard StudioInstant EFTR 272,61FailedTimed out at the bank
10:50INV-4147Halyard StudioCapitec PayR 82,96FailedIssuer declined
10:47INV-4148Muizenberg Surf CoCapitec PayR 429,83Authorised
10:42INV-4149Halyard StudioInstant EFTR 1 676,07Settled
10:38INV-4150Ubuntu BooksEFTR 24,54Settled
10:34INV-4151Muizenberg Surf CoCapitec PayR 53,92Settled
10:30INV-4152Table Bay CyclesCardR 58,41Settled
10:26INV-4153Sandton DentalEFTR 90,63Authorised
10:23INV-4154Table Bay CyclesCardR 334,02Settled
10:19INV-4155Umhlanga YogaInstant EFTR 269,78Settled
10:14INV-4156Ubuntu BooksEFTR 190,64Authorised
10:10INV-4157Muizenberg Surf CoEFTR 92,99Authorised
10:07INV-4158Sandton DentalCapitec PayR 245,58ReversedInsufficient funds
10:02INV-4159Umhlanga YogaCardR 308,50Settled

How it is built

Money is an integer number of cents everywhere, divided by a hundred once, at the edge, when it is formatted. A dashboard whose totals are out by a cent because 0.1 + 0.2 is the one domain error somebody who works in payments spots instantly — and they spot it in the summary rather than in the row that caused it.

Refunds and reversals are not netted off the gross. One combined figure hides the difference between a quiet day and a day with a lot of both, which is the entire thing a merchant opens this screen to find out.

A settled payment does not move. Onlyauthorised transitions, and only to settled or reversed. The feed is a lookup table rather than a random walk, because a dashboard showing something no acquirer does would be wrong about the thing this piece exists to be right about.

There is no chart library. A module turns a series into rectangles with coordinates and the component draws them, which means the claims worth making about a chart — a zero bar has no height, the tallest fills the plot, an empty series does not divide by zero, the axis starts at zero — are assertions over plain numbers. Each chart also ships the same figures as a real table, hidden visually. A chart whose only accessible form is “bar chart” is an image with no alt text.

Sorting is total, not merely stable. Several rows share a merchant, so the comparison falls back to the transaction id. Otherwise their order is whatever the engine’s sort does — stable in every current engine, which means the bug that produces would never appear here and would appear somewhere.

Reduced motion does not slow the feed down. It does not start it. A table that rewrites itself every two and a half seconds is exactly the unrequested movement the setting asks to be spared, and a slower version of it is still it. What replaces it isAdvance one — the same answerthe flow field gives, where reduced motion composes a still and hands you a Step button. Pause and Play are there for everybody regardless: auto-updating content needs a stop whoever is reading it.

Nothing here fetches. The site sendsconnect-src 'none', so a feed that polled would be refused by the browser. Live means a deterministic state transition on an interval — which is also why the same seed always produces the same ledger, and why the tests can make claims about tick 40.

The merchants, amounts and status mix are invented. The proportions are plausible rather than measured — an even split across five statuses would put the failure rate at twenty per cent, which is not a business.