diff --git a/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/README.md b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/README.md new file mode 100644 index 00000000..797a6d18 --- /dev/null +++ b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/README.md @@ -0,0 +1,27 @@ +# ๐Ÿ’น Crypto Tracker Dashboard Pro + +**Contributor:** Keron Patel + +## ๐Ÿงพ Description +A realโ€‘time **cryptocurrency tracker dashboard** built using **HTML, CSS, and JavaScript**, featuring **live market data**, **multiโ€‘coin comparison charts**, **currency selector**, **dark/light theme**, and **price alerts**. +Data powered by the **Coingecko Public API**. + +## โš™๏ธ Features +- ๐Ÿ”„ **Live Market Data** โ€“ Auto refreshes every minute. +- ๐Ÿ’ฑ **Currency Switcher** โ€“ Instantly view prices in USD or INR. +- ๐Ÿ“Š **Multiโ€‘Coin Chart** โ€“ Compare multiple coins on one chart using Chart.js. +- ๐ŸŒ— **Dark / Light Mode Toggle** โ€“ Seamless theme switch for better viewing. +- ๐Ÿ”” **Price Alerts** โ€“ Simulated notifications for high volatility coins. +- ๐Ÿงฉ **Responsive Design** โ€“ Works smoothly on desktop and mobile screens. + +## ๐Ÿ›  Tech Stack +- HTML5 +- CSS3 +- JavaScript (ES6) +- Chart.js +- Coingecko API + +## ๐Ÿš€ How to Run +1. Clone or download this repository. +2. Open the `index.html` file in your web browser. +3. Explore live crypto data, switch currency, toggle themes, and view charts. diff --git a/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/index.html b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/index.html new file mode 100644 index 00000000..50db8f0c --- /dev/null +++ b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/index.html @@ -0,0 +1,39 @@ + + + + + + Crypto Tracker Dashboard ๐Ÿ’น + + + + +
+

๐Ÿ’ฐ Crypto Tracker Dashboard

+ +
+ + + + + +
+
+ +
+
+ + + +
+ + + + + + \ No newline at end of file diff --git a/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/script.js b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/script.js new file mode 100644 index 00000000..9f2fc5ba --- /dev/null +++ b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/script.js @@ -0,0 +1,128 @@ +const statsContainer = document.getElementById("stats"); +const searchInput = document.getElementById("searchInput"); +const chartCanvas = document.getElementById("priceChart"); +const currencySelect = document.getElementById("currencySelect"); +const themeToggle = document.getElementById("themeToggle"); +const alertBox = document.getElementById("alertBox"); + +let cryptoChart; +let currentCurrency = "usd"; +let allCoins = []; + +// First call +fetchData(); + +// Fetch data based on currency +async function fetchData() { + const url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currentCurrency}&order=market_cap_desc&per_page=10&page=1&sparkline=true`; + try { + const res = await fetch(url); + const data = await res.json(); + allCoins = data; + displayCoins(allCoins); + drawChart(allCoins.slice(0, 3)); // Initial comparison (top 3 coins) + } catch (err) { + statsContainer.innerHTML = "

Error fetching data โš ๏ธ

"; + } +} + +// Display coin cards +function displayCoins(coins) { + statsContainer.innerHTML = ""; + coins.forEach((coin) => { + const card = document.createElement("div"); + card.classList.add("coin-card"); + card.innerHTML = ` + ${coin.name} +

${coin.name}

+

Symbol: ${coin.symbol.toUpperCase()}

+

๐Ÿ’ฐ Price: ${currentCurrency === "usd" ? "$" : "โ‚น"}${coin.current_price.toLocaleString()}

+

๐Ÿ“ˆ 24h: ${coin.price_change_percentage_24h.toFixed(2)}%

+

Rank: #${coin.market_cap_rank}

+ `; + card.addEventListener("click", () => drawChart([coin])); + statsContainer.appendChild(card); + simulateAlert(coin); + }); +} + +// Draw comparison chart (supports multiple coins) +function drawChart(coins) { + const datasets = coins.map((coin) => ({ + label: `${coin.name}`, + data: coin.sparkline_in_7d.price, + borderColor: randomColor(), + borderWidth: 2, + fill: false, + tension: 0.3 + })); + + const labels = Array.from({ length: coins[0].sparkline_in_7d.price.length }, (_, i) => i + 1); + if (cryptoChart) cryptoChart.destroy(); + + cryptoChart = new Chart(chartCanvas, { + type: "line", + data: { labels, datasets }, + options: { + responsive: true, + plugins: { + legend: { labels: { color: getComputedStyle(document.body).getPropertyValue("--text") } } + }, + scales: { + x: { display: false }, + y: { + ticks: { color: getComputedStyle(document.body).getPropertyValue("--muted") }, + grid: { color: getComputedStyle(document.body).getPropertyValue("--card-bg") } + } + } + } + }); +} + +// Search +searchInput.addEventListener("input", () => { + const query = searchInput.value.toLowerCase(); + const filtered = allCoins.filter(c => c.name.toLowerCase().includes(query)); + displayCoins(filtered.length ? filtered : allCoins); +}); + +// Currency switch +currencySelect.addEventListener("change", () => { + currentCurrency = currencySelect.value; + fetchData(); + showAlert(`Currency switched to ${currentCurrency.toUpperCase()}`); +}); + +// Theme toggle +themeToggle.addEventListener("click", () => { + document.body.classList.toggle("light"); + const mode = document.body.classList.contains("light") ? "Light" : "Dark"; + themeToggle.textContent = mode === "Light" ? "โ˜€๏ธ Light Mode" : "๐ŸŒ™ Dark Mode"; + showAlert(`${mode} theme activated`); + drawChart(allCoins.slice(0, 3)); // reโ€‘render chart for theme contrast +}); + +// Simulated price alert when 24h change more than 5% +function simulateAlert(coin) { + if (Math.abs(coin.price_change_percentage_24h) > 5) { + showAlert(`${coin.name} price moved ${coin.price_change_percentage_24h.toFixed(2)}%! ๐Ÿšจ`); + } +} + +// Alert box popup +function showAlert(text) { + alertBox.textContent = text; + alertBox.classList.remove("hidden"); + setTimeout(() => { alertBox.classList.add("hidden"); }, 4000); +} + +// Random color for comparison lines +function randomColor() { + const r = Math.floor(Math.random() * 255); + const g = Math.floor(Math.random() * 255); + const b = Math.floor(Math.random() * 255); + return `rgb(${r},${g},${b})`; +} + +// Auto refresh every minute +setInterval(fetchData, 60000); \ No newline at end of file diff --git a/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/style.css b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/style.css new file mode 100644 index 00000000..98a87266 --- /dev/null +++ b/Domains/Frontend/MiniProjects/crypto-tracker-dashboard/style.css @@ -0,0 +1,124 @@ +:root { + --bg: #0d1117; + --card-bg: #161b22; + --text: #ffffff; + --muted: #8b949e; + --accent: #00ff94; +} + +/* Light theme overrides */ +body.light { + --bg: #ffffff; + --card-bg: #f5f5f5; + --text: #222; + --muted: #555; + --accent: #0088ff; +} + +body { + margin: 0; + font-family: 'Poppins', sans-serif; + background-color: var(--bg); + color: var(--text); + text-align: center; + transition: 0.3s; +} + +header { + padding: 20px; + background: var(--card-bg); + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + box-shadow: 0 2px 10px rgba(0,0,0,0.5); +} + +.controls { + display: flex; + gap: 10px; + flex-wrap: wrap; + justify-content: center; +} + +input, select, button { + padding: 10px; + border-radius: 5px; + border: 1px solid var(--muted); + background: var(--bg); + color: var(--text); +} + +button { + cursor: pointer; + background: var(--accent); + color: #000; + border: none; + font-weight: 600; + transition: transform 0.2s; +} +button:hover { transform: scale(1.05); } + +#stats { + margin: 30px auto; + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 20px; +} + +.coin-card { + background: var(--card-bg); + padding: 20px; + border-radius: 10px; + width: 200px; + box-shadow: 0 0 10px rgba(255,255,255,0.05); + transition: transform 0.2s; +} +.coin-card:hover { transform: scale(1.05); } + +.coin-card img { + width: 40px; + height: 40px; +} + +.coin-card h3 { + margin: 10px 0 0; + font-size: 1.1em; +} + +.coin-card p { + margin: 5px 0; + color: var(--muted); +} + +canvas { + width: 90%; + max-width: 800px; + margin: 30px auto; + background: var(--card-bg); + border-radius: 10px; + padding: 20px; +} + +footer { + margin-top: 40px; + padding: 10px; + background: var(--card-bg); + color: var(--muted); +} + +#alertBox { + position: fixed; + bottom: 20px; + right: 20px; + background: var(--accent); + color: #000; + padding: 12px 18px; + border-radius: 8px; + font-weight: bold; + box-shadow: 0 0 10px rgba(0,0,0,0.3); + opacity: 0.9; + transition: opacity 0.4s; +} +.hidden { display: none; } \ No newline at end of file