Optimistic updates for +/- buttons, UI responds instantly
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-05-16 02:14:18 +02:00
parent d0817c7476
commit 1a545d3a8f
2 changed files with 8 additions and 18 deletions
+6 -17
View File
@@ -1,24 +1,21 @@
import React, { useContext, useState } from 'react'; import React, { useContext } from 'react';
import { CardContext } from '../../context/CardContext'; import { CardContext } from '../../context/CardContext';
import { updateCardAmount } from '../../services/api'; import { updateCardAmount } from '../../services/api';
function PrintingRow({ card_id, printing, cols, zebra }) { function PrintingRow({ card_id, printing, cols, zebra }) {
const { ownedAmounts, updateAmount } = useContext(CardContext); const { ownedAmounts, updateAmount } = useContext(CardContext);
const [loading, setLoading] = useState(false);
const key = `${printing.set_id}-${printing.rarity_id}`; const key = `${printing.set_id}-${printing.rarity_id}`;
const current = ownedAmounts[card_id]?.[key] ?? printing.amount_owned ?? 0; const current = ownedAmounts[card_id]?.[key] ?? printing.amount_owned ?? 0;
const save = async (next) => { const save = async (next) => {
if (card_id == null || printing.set_id == null || printing.rarity_id == null) return; if (card_id == null || printing.set_id == null || printing.rarity_id == null) return;
setLoading(true); updateAmount(card_id, key, next);
try { try {
await updateCardAmount(card_id, printing.set_id, printing.rarity_id, next); await updateCardAmount(card_id, printing.set_id, printing.rarity_id, next);
updateAmount(card_id, key, next);
} catch (err) { } catch (err) {
console.error('Failed to update amount', err); console.error('Failed to update amount', err);
} finally { updateAmount(card_id, key, current);
setLoading(false);
} }
}; };
@@ -26,7 +23,7 @@ function PrintingRow({ card_id, printing, cols, zebra }) {
<div style={{ <div style={{
display: 'grid', gridTemplateColumns: cols, display: 'grid', gridTemplateColumns: cols,
gap: '8px', padding: '7px 16px 7px 32px', gap: '8px', padding: '7px 16px 7px 32px',
alignItems: 'center', opacity: loading ? 0.5 : 1, alignItems: 'center',
background: zebra ? '#1e1e1e' : '#161616', background: zebra ? '#1e1e1e' : '#161616',
}}> }}>
<span style={{ fontFamily: 'monospace', fontSize: '11px', color: '#555' }}> <span style={{ fontFamily: 'monospace', fontSize: '11px', color: '#555' }}>
@@ -35,19 +32,11 @@ function PrintingRow({ card_id, printing, cols, zebra }) {
<span style={{ fontSize: '12px', color: '#888' }}>{printing.set_name}</span> <span style={{ fontSize: '12px', color: '#888' }}>{printing.set_name}</span>
<span style={{ fontSize: '12px', color: '#aaa' }}>{printing.rarity_name}</span> <span style={{ fontSize: '12px', color: '#aaa' }}>{printing.rarity_name}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}> <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<button <button className="icon-btn" onClick={() => current > 0 && save(current - 1)} disabled={current === 0}></button>
className="icon-btn"
onClick={() => current > 0 && save(current - 1)}
disabled={loading || current === 0}
></button>
<span style={{ minWidth: '20px', textAlign: 'center', color: '#e0e0e0', fontSize: '13px' }}> <span style={{ minWidth: '20px', textAlign: 'center', color: '#e0e0e0', fontSize: '13px' }}>
{current} {current}
</span> </span>
<button <button className="icon-btn" onClick={() => save(current + 1)}>+</button>
className="icon-btn"
onClick={() => save(current + 1)}
disabled={loading}
>+</button>
</div> </div>
</div> </div>
); );
+2 -1
View File
@@ -44,11 +44,12 @@ function SetCardRow({ card, zebra }) {
const current = ownedAmounts[card.id]?.[key] ?? card.amount_owned ?? 0; const current = ownedAmounts[card.id]?.[key] ?? card.amount_owned ?? 0;
const save = async (next) => { const save = async (next) => {
updateAmount(card.id, key, next);
try { try {
await updateCardAmount(card.id, card.set_id, card.rarity_id, next); await updateCardAmount(card.id, card.set_id, card.rarity_id, next);
updateAmount(card.id, key, next);
} catch (err) { } catch (err) {
console.error('Failed to update amount', err); console.error('Failed to update amount', err);
updateAmount(card.id, key, current);
} }
}; };