fix: prevent immediate elo update on listing selection
This commit is contained in:
@@ -9,7 +9,7 @@ interface Toast {
|
|||||||
|
|
||||||
export default function CompareView() {
|
export default function CompareView() {
|
||||||
const [matchup, setMatchup] = useState<Matchup | null>(null);
|
const [matchup, setMatchup] = useState<Matchup | null>(null);
|
||||||
const [result, setResult] = useState<CompareResult | null>(null);
|
const [selected, setSelected] = useState<{ winner: Listing; loser: Listing } | null>(null);
|
||||||
const [toasts, setToasts] = useState<Toast[]>([]);
|
const [toasts, setToasts] = useState<Toast[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
@@ -19,7 +19,7 @@ export default function CompareView() {
|
|||||||
|
|
||||||
const fetchMatchup = useCallback(async () => {
|
const fetchMatchup = useCallback(async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setResult(null);
|
setSelected(null);
|
||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const m = await api.getMatchup();
|
const m = await api.getMatchup();
|
||||||
@@ -35,18 +35,26 @@ export default function CompareView() {
|
|||||||
fetchMatchup();
|
fetchMatchup();
|
||||||
}, [fetchMatchup]);
|
}, [fetchMatchup]);
|
||||||
|
|
||||||
const handlePick = async (winner: Listing, loser: Listing) => {
|
const handlePick = (winner: Listing, loser: Listing) => {
|
||||||
if (submitting) return;
|
setSelected({ winner, loser });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = async () => {
|
||||||
|
if (!selected || submitting) return;
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
try {
|
try {
|
||||||
const res = await api.submitComparison(winner.global_id, loser.global_id);
|
const res = await api.submitComparison(selected.winner.global_id, selected.loser.global_id);
|
||||||
setResult(res);
|
|
||||||
setComparisonCount((c) => c + 1);
|
setComparisonCount((c) => c + 1);
|
||||||
|
|
||||||
// Add toast
|
// Add toast
|
||||||
const id = ++toastId.current;
|
const id = ++toastId.current;
|
||||||
setToasts((prev) => [...prev, { id, result: res }]);
|
setToasts((prev) => [...prev, { id, result: res }]);
|
||||||
setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), 3000);
|
setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), 3000);
|
||||||
|
|
||||||
|
// Load next pair
|
||||||
|
setSelected(null);
|
||||||
|
const m = await api.getMatchup();
|
||||||
|
setMatchup(m);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e instanceof Error ? e.message : "Failed to submit comparison");
|
setError(e instanceof Error ? e.message : "Failed to submit comparison");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -95,13 +103,13 @@ export default function CompareView() {
|
|||||||
listing={matchup.listing_a}
|
listing={matchup.listing_a}
|
||||||
onClick={() => handlePick(matchup.listing_a, matchup.listing_b)}
|
onClick={() => handlePick(matchup.listing_a, matchup.listing_b)}
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
highlight={result?.winner_id === matchup.listing_a.global_id}
|
highlight={selected?.winner.global_id === matchup.listing_a.global_id}
|
||||||
/>
|
/>
|
||||||
<ListingCard
|
<ListingCard
|
||||||
listing={matchup.listing_b}
|
listing={matchup.listing_b}
|
||||||
onClick={() => handlePick(matchup.listing_b, matchup.listing_a)}
|
onClick={() => handlePick(matchup.listing_b, matchup.listing_a)}
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
highlight={result?.winner_id === matchup.listing_b.global_id}
|
highlight={selected?.winner.global_id === matchup.listing_b.global_id}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -112,12 +120,13 @@ export default function CompareView() {
|
|||||||
>
|
>
|
||||||
Skip
|
Skip
|
||||||
</button>
|
</button>
|
||||||
{result && (
|
{selected && (
|
||||||
<button
|
<button
|
||||||
onClick={fetchMatchup}
|
onClick={handleNext}
|
||||||
className="px-6 py-2 bg-indigo-600 text-white rounded-lg text-sm font-medium hover:bg-indigo-700 transition-colors"
|
disabled={submitting}
|
||||||
|
className="px-6 py-2 bg-indigo-600 text-white rounded-lg text-sm font-medium hover:bg-indigo-700 transition-colors disabled:opacity-50"
|
||||||
>
|
>
|
||||||
Next pair →
|
{submitting ? "Submitting..." : "Next pair →"}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -138,7 +147,7 @@ export default function CompareView() {
|
|||||||
<p className="text-xs text-slate-500">Comparison recorded</p>
|
<p className="text-xs text-slate-500">Comparison recorded</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between mt-2 text-sm">
|
<div className="flex items-center justify-between gap-4 mt-2 text-sm">
|
||||||
<span className="text-green-600 font-bold">
|
<span className="text-green-600 font-bold">
|
||||||
Winner: {t.result.new_winner_elo.toFixed(0)}{" "}
|
Winner: {t.result.new_winner_elo.toFixed(0)}{" "}
|
||||||
<span className="text-green-500 text-xs">(+{t.result.elo_change.toFixed(1)})</span>
|
<span className="text-green-500 text-xs">(+{t.result.elo_change.toFixed(1)})</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user