From 68c35eb9caa0c0389e6cd96503c48c4f712bf29b Mon Sep 17 00:00:00 2001 From: anmolsah Date: Wed, 15 Oct 2025 21:23:37 +0530 Subject: [PATCH] Added pagination for top coins in Crypto.jsx (#41) --- src/pages/Crypto.jsx | 59 +++++++++++++++++++++++++++++++++----------- src/styles.css | 32 ++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/pages/Crypto.jsx b/src/pages/Crypto.jsx index 645d268..b58b3ab 100644 --- a/src/pages/Crypto.jsx +++ b/src/pages/Crypto.jsx @@ -18,46 +18,77 @@ * - [ ] Dark mode adaptive coloring for charts * - [ ] Extract to service + custom hook (useCryptoMarkets) */ -import { useEffect, useState } from 'react'; -import Loading from '../components/Loading.jsx'; -import ErrorMessage from '../components/ErrorMessage.jsx'; -import Card from '../components/Card.jsx'; +import { useEffect, useState } from "react"; +import Loading from "../components/Loading.jsx"; +import ErrorMessage from "../components/ErrorMessage.jsx"; +import Card from "../components/Card.jsx"; export default function Crypto() { const [coins, setCoins] = useState([]); - const [query, setQuery] = useState(''); + const [query, setQuery] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); + const [page, setPage] = useState(1); - useEffect(() => { fetchCoins(); }, []); + useEffect(() => { + fetchCoins(); + }, [page]); async function fetchCoins() { try { - setLoading(true); setError(null); - const res = await fetch('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=50&page=1&sparkline=false'); - if (!res.ok) throw new Error('Failed to fetch'); + setLoading(true); + setError(null); + const res = await fetch( + `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=50&page=${page}&sparkline=false` + ); + if (!res.ok) throw new Error("Failed to fetch"); const json = await res.json(); setCoins(json); - } catch (e) { setError(e); } finally { setLoading(false); } + } catch (e) { + setError(e); + } finally { + setLoading(false); + } } - const filtered = coins.filter(c => c.name.toLowerCase().includes(query.toLowerCase())); + const filtered = coins.filter((c) => + c.name.toLowerCase().includes(query.toLowerCase()) + ); return (

Cryptocurrency Tracker

- setQuery(e.target.value)} placeholder="Search coin" /> + setQuery(e.target.value)} + placeholder="Search coin" + /> + {loading && }
- {filtered.map(c => ( - ${c.current_price}}> + {filtered.map((c) => ( + ${c.current_price}} + >

Market Cap: ${c.market_cap.toLocaleString()}

24h: {c.price_change_percentage_24h?.toFixed(2)}%

{/* TODO: Add mini sparkline chart */}
))}
+ +
+ + + Page {page} + + +
); } diff --git a/src/styles.css b/src/styles.css index c1fb955..af31d51 100644 --- a/src/styles.css +++ b/src/styles.css @@ -412,3 +412,35 @@ blockquote { @media (max-width: 640px) { .weather-inner { padding: 1rem; } } + + +/**Pagination **/ + +.pagination { + width: 100%; + display: flex; + justify-content: center; + align-items: center; + margin-top: 20px; + gap: 15px; +} + +.pagination button { + padding: 8px 16px; + border-radius: 5px; + border: none; + background-color: #007bff; + color: white; + font-weight: bold; + cursor: pointer; + transition: background-color 0.2s; +} + +.pagination button:hover { + background-color: #0056b3; +} + +.pagination button:disabled { + background-color: #ccc; + cursor: not-allowed; +}