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
27 changes: 27 additions & 0 deletions Domains/Frontend/MiniProjects/crypto-tracker-dashboard/README.md
Original file line number Diff line number Diff line change
@@ -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.
39 changes: 39 additions & 0 deletions Domains/Frontend/MiniProjects/crypto-tracker-dashboard/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Crypto Tracker Dashboard 💹</title>
<link rel="stylesheet" href="style.css" />
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<header>
<h1>💰 Crypto Tracker Dashboard</h1>

<div class="controls">
<input type="text" id="searchInput" placeholder="Search coin name..." />

<select id="currencySelect">
<option value="usd">USD</option>
<option value="inr">INR</option>
</select>

<button id="themeToggle">🌙 Dark Mode</button>
</div>
</header>

<main>
<section id="stats"></section>
<canvas id="priceChart"></canvas>

<div id="alertBox" class="hidden"></div>
</main>

<footer>
<p>Made with ❤️ by Keron Patel | Data from Coingecko API</p>
</footer>

<script src="script.js"></script>
</body>
</html>
128 changes: 128 additions & 0 deletions Domains/Frontend/MiniProjects/crypto-tracker-dashboard/script.js
Original file line number Diff line number Diff line change
@@ -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 = "<p style='color:red;'>Error fetching data ⚠️</p>";
}
}

// Display coin cards
function displayCoins(coins) {
statsContainer.innerHTML = "";
coins.forEach((coin) => {
const card = document.createElement("div");
card.classList.add("coin-card");
card.innerHTML = `
<img src="${coin.image}" alt="${coin.name}" />
<h3>${coin.name}</h3>
<p>Symbol: ${coin.symbol.toUpperCase()}</p>
<p>💰 Price: ${currentCurrency === "usd" ? "$" : "₹"}${coin.current_price.toLocaleString()}</p>
<p>📈 24h: ${coin.price_change_percentage_24h.toFixed(2)}%</p>
<p>Rank: #${coin.market_cap_rank}</p>
`;
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);
124 changes: 124 additions & 0 deletions Domains/Frontend/MiniProjects/crypto-tracker-dashboard/style.css
Original file line number Diff line number Diff line change
@@ -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; }
Loading