diff options
| author | Adam Soltys <[email protected]> | 2026-07-05 20:13:49 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-07-05 20:13:49 -0700 |
| commit | 0408609fc68fa71ff705ef7a241880efefddcc3f (patch) | |
| tree | 5475ff40e9bfbd852d2acc4a4b711f2d8e4389b7 | |
| parent | 89a87b6b7866240a9289aefb3975a607d61bf371 (diff) | |
| download | coinosv3-0408609fc68fa71ff705ef7a241880efefddcc3f.tar.gz coinosv3-0408609fc68fa71ff705ef7a241880efefddcc3f.zip | |
Gift detail: direct Reclaim/Revoke buttons, no empty summary box
The Cancel-then-confirm step is gone: a reserved gift offers View /
Reclaim / Revoke immediately, a reclaimed one just Revoke. The summary
box only renders when it has content — a reclaimed gift with no
recorded date drew an empty gray box.
Co-Authored-By: Claude Fable 5 <[email protected]>
| -rw-r--r-- | src/features/gifts.js | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/src/features/gifts.js b/src/features/gifts.js index de6c9c3..e4a445f 100644 --- a/src/features/gifts.js +++ b/src/features/gifts.js @@ -734,24 +734,27 @@ export function giftsFeature(ctx) { amt != null ? h('div', { class: 'amt', style: 'font-size:30px' }, h('span', { class: 'amount' }, fmtAmount(amt)), ' ', unitTag('unit')) : null, - h('div', { class: 'summary col', style: 'gap:0' }, - created ? line(t('dateLabel'), new Date(created).toLocaleString()) : null, - !g.claimed && g.reserved ? line(t('status'), t('lockedInGifts')) : null), - ui.revokeId === g.id - ? h('div', { class: 'col', style: 'gap:8px' }, + // only render the summary box when it has content (an empty gray box + // otherwise appears for reclaimed gifts with no recorded date) + created || (!g.claimed && g.reserved) + ? h('div', { class: 'summary col', style: 'gap:0' }, + created ? line(t('dateLabel'), new Date(created).toLocaleString()) : null, + !g.claimed && g.reserved ? line(t('status'), t('lockedInGifts')) : null) + : null, + // Reclaim/Revoke up front — no confirm step. A reserved gift offers both; + // an already-reclaimed one only Revoke (its coin is spendable again, only + // the live link is left to kill). + g.claimed + ? null + : h('div', { class: 'col', style: 'gap:8px' }, h('span', { class: 'small muted' }, g.reserved ? t('giftReclaimPrompt') : t('giftRevokeConfirm')), ui.busy ? h('button', { class: 'btn-primary btn-block', disabled: true }, h('span', { class: 'spinner' })) : h('div', { class: 'row gap6' }, + rec ? h('button', { class: 'grow', onClick: () => { ui.viewGift = rec; render(); } }, t('giftView')) : null, g.reserved ? h('button', { class: 'btn-ghost grow', onClick: () => doReclaim(g.id) }, t('giftReclaim')) : null, - h('button', { class: 'btn-primary grow', onClick: () => doRevoke(g.id) }, t('giftRevoke'))), - ui.busy ? null : h('button', { class: 'btn-ghost btn-block', onClick: () => { ui.revokeId = null; render(); } }, t('back'))) - : g.claimed - ? null - : h('div', { class: 'row gap6' }, - rec ? h('button', { class: 'grow', onClick: () => { ui.viewGift = rec; render(); } }, t('giftView')) : null, - h('button', { class: 'grow', onClick: () => { ui.revokeId = g.id; render(); } }, t('giftCancel'))), - ui.revokeId === g.id ? null : h('button', { class: 'btn-ghost btn-block', onClick: back }, t('back')) + h('button', { class: 'btn-primary grow', onClick: () => doRevoke(g.id) }, t('giftRevoke')))), + h('button', { class: 'btn-ghost btn-block', onClick: back }, t('back')) ); } |
