Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion frontend/src/components/PlatformStats.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ export default function PlatformStats() {
setLastRefresh(new Date());
} catch (error) {
console.error('Failed to fetch platform stats:', error.message || error);
setError('Unable to load platform statistics. Please try again later.');
const isNetworkError = error.message?.includes('fetch') || error.message?.includes('network') || error.name === 'TypeError';
setError(
isNetworkError
? 'Unable to reach the Stacks API. Check your connection and try again.'
: `Failed to load platform statistics: ${error.message || 'Unknown error'}`
);
setLoading(false);
}
}, []);
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/RecentTips.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
const [sortBy, setSortBy] = useState('newest');
const [showFilters, setShowFilters] = useState(false);
const [offset, setOffset] = useState(0);
const [totalResults, setTotalResults] = useState(0);

Check failure on line 29 in frontend/src/components/RecentTips.jsx

View workflow job for this annotation

GitHub Actions / Frontend Lint

'totalResults' is assigned a value but never used. Allowed unused vars must match /^[A-Z_]/u

const fetchRecentTips = useCallback(async () => {
try {
Expand Down Expand Up @@ -55,7 +55,12 @@
setLastRefresh(new Date());
} catch (err) {
console.error('Failed to fetch recent tips:', err.message || err);
setError(err.message || 'Failed to load tips');
const isNetworkError = err.message?.includes('fetch') || err.message?.includes('network') || err.name === 'TypeError';
setError(
isNetworkError
? 'Unable to reach the Stacks API. Check your connection and try again.'
: `Failed to load tips: ${err.message || 'Unknown error'}`
);
setLoading(false);
}
}, []);
Expand Down
31 changes: 28 additions & 3 deletions frontend/src/components/TipHistory.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ export default function TipHistory({ userAddress }) {
const [stats, setStats] = useState(null);
const [tips, setTips] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [tab, setTab] = useState('all');
const [lastRefresh, setLastRefresh] = useState(null);

const fetchData = useCallback(async () => {
if (!userAddress) return;
try {
setError(null);
const [statsResult, tipsResult] = await Promise.all([
fetchCallReadOnlyFunction({
network,
Expand All @@ -31,7 +33,10 @@ export default function TipHistory({ userAddress }) {
}),
fetch(
`${API_BASE}/extended/v1/contract/${CONTRACT_ADDRESS}.${CONTRACT_NAME}/events?limit=50&offset=0`
).then(r => r.json())
).then(r => {
if (!r.ok) throw new Error(`API returned ${r.status}`);
return r.json();
})
]);

const jsonResult = cvToJSON(statsResult);
Expand All @@ -50,8 +55,14 @@ export default function TipHistory({ userAddress }) {
setTips(userTips);
setLoading(false);
setLastRefresh(new Date());
} catch (error) {
console.error('Failed to fetch tip history:', error.message || error);
} catch (err) {
console.error('Failed to fetch tip history:', err.message || err);
const isNetworkError = err.message?.includes('fetch') || err.message?.includes('network') || err.name === 'TypeError';
setError(
isNetworkError
? 'Unable to reach the Stacks API. Check your connection and try again.'
: `Failed to load activity: ${err.message || 'Unknown error'}`
);
setLoading(false);
}
}, [userAddress]);
Expand Down Expand Up @@ -106,6 +117,20 @@ export default function TipHistory({ userAddress }) {
);
}

if (error) {
return (
<div className="max-w-md mx-auto text-center py-12 bg-white dark:bg-gray-900 rounded-2xl border border-red-100 dark:border-red-900/30 p-8">
<p className="text-red-600 dark:text-red-400 font-medium mb-4">{error}</p>
<button
onClick={() => { setError(null); setLoading(true); fetchData(); }}
className="px-6 py-2 bg-slate-900 dark:bg-white dark:text-gray-900 text-white rounded-xl font-bold hover:bg-black dark:hover:bg-gray-100 transition-colors"
>
Retry
</button>
</div>
);
}

if (!stats) {
return (
<div className="text-center py-12 bg-gray-50 rounded-xl border-2 border-dashed border-gray-200">
Expand Down
Loading