fix: improve error handling in admin trades fetch functions

- Return errors from fetch functions instead of setting state directly
- Clear error state before starting a new fetch
- Combine errors when both upcoming and past trades fail to load
- Handle fetch errors in handleAction as well
This commit is contained in:
counterweight 2025-12-23 12:25:15 +01:00
parent e8d0ee2eca
commit 06ad7fefe1
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C

View file

@ -45,17 +45,18 @@ export default function AdminTradesPage() {
const [statusFilter, setStatusFilter] = useState<string>("all");
const [userSearch, setUserSearch] = useState("");
const fetchUpcomingTrades = useCallback(async () => {
const fetchUpcomingTrades = useCallback(async (): Promise<string | null> => {
try {
const data = await api.get<AdminExchangeResponse[]>("/api/admin/trades/upcoming");
setUpcomingTrades(data);
return null;
} catch (err) {
console.error("Failed to fetch upcoming trades:", err);
setError("Failed to load upcoming trades");
return "Failed to load upcoming trades";
}
}, []);
const fetchPastTrades = useCallback(async () => {
const fetchPastTrades = useCallback(async (): Promise<string | null> => {
try {
let url = "/api/admin/trades/past";
const params = new URLSearchParams();
@ -73,18 +74,28 @@ export default function AdminTradesPage() {
const data = await api.get<AdminExchangeResponse[]>(url);
setPastTrades(data);
return null;
} catch (err) {
console.error("Failed to fetch past trades:", err);
setError("Failed to load past trades");
return "Failed to load past trades";
}
}, [statusFilter, userSearch]);
useEffect(() => {
if (user && isAuthorized) {
setIsLoadingTrades(true);
Promise.all([fetchUpcomingTrades(), fetchPastTrades()]).finally(() => {
setIsLoadingTrades(false);
});
setError(null);
Promise.all([fetchUpcomingTrades(), fetchPastTrades()])
.then(([upcomingErr, pastErr]) => {
// Combine errors if both failed
const errors = [upcomingErr, pastErr].filter(Boolean);
if (errors.length > 0) {
setError(errors.join("; "));
}
})
.finally(() => {
setIsLoadingTrades(false);
});
}
}, [user, isAuthorized, fetchUpcomingTrades, fetchPastTrades]);
@ -99,7 +110,12 @@ export default function AdminTradesPage() {
: `/api/admin/trades/${tradeId}/${action}`;
await api.post<AdminExchangeResponse>(endpoint, {});
await Promise.all([fetchUpcomingTrades(), fetchPastTrades()]);
// Refetch trades - errors from fetch are informational, not critical
const [upcomingErr, pastErr] = await Promise.all([fetchUpcomingTrades(), fetchPastTrades()]);
const fetchErrors = [upcomingErr, pastErr].filter(Boolean);
if (fetchErrors.length > 0) {
setError(fetchErrors.join("; "));
}
setConfirmAction(null);
} catch (err) {
setError(err instanceof Error ? err.message : `Failed to ${action} trade`);