component
Payouts dialog
"View payouts" for a tournament pack: a button that opens the payout table the solve used, equal prizes collapsed into one row.
The payout table a tournament pack was solved with, behind a View payouts button. Equal prizes collapse into one row.
Sample data
Installation
$ npx shadcn@latest add https://www.pokerstudy.ai/r/payouts-dialog.jsonProps
Generated from the component source with react-docgen-typescript.
PayoutsDialog
| Prop | Type | Default | Description |
|---|---|---|---|
| paid * | string | – | "30 paid (15%)", the header cell's value. |
| payouts * | readonly number[] | – | Prize per paid place, 1st first, in dollars. |
| source * | string | – | Where the table comes from, under the title. |
Source
lib/pokerdata/payouts.ts
/** "1st", "2nd", "11th". */
export function ordinal(n: number): string {
const mod100 = n % 100;
const suffix =
mod100 >= 11 && mod100 <= 13 ? "th" : (["th", "st", "nd", "rd"][n % 10] ?? "th");
return `${n}${suffix}`;
}
export const dollars = (n: number) => `$${n.toLocaleString("en-US")}`;
/** Equal prizes in a run collapse to one row: "10th–11th · $748". */
export function payoutRows(payouts: readonly number[]) {
const rows: { places: string; first: number; prize: number; share: number }[] = [];
const pool = payouts.reduce((t, p) => t + p, 0);
let start = 0;
while (start < payouts.length) {
let end = start;
while (end + 1 < payouts.length && payouts[end + 1] === payouts[start]) end++;
rows.push({
places: start === end ? ordinal(start + 1) : `${ordinal(start + 1)}–${ordinal(end + 1)}`,
first: start + 1,
prize: payouts[start],
share: payouts[start] / pool,
});
start = end + 1;
}
return rows;
}