flitrx's picture
Design a neomorphic cryptocurrency tracker website using Web3 with blockchain integration. Make this a fully functional ready to launch website. Provide detailed specifications for user experience, technical architecture, and monetization strategy.
83820df verified
class CryptoCard extends HTMLElement {
connectedCallback() {
const cryptoData = JSON.parse(this.getAttribute('data-crypto'));
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
.crypto-card {
background: linear-gradient(145deg, #1f2937, #111827);
border-radius: 20px;
padding: 1.5rem;
transition: all 0.3s ease;
cursor: pointer;
position: relative;
overflow: hidden;
}
.crypto-card:hover {
transform: translateY(-8px);
box-shadow: 15px 15px 30px #0a0e14, -15px -15px 30px #243142;
}
.crypto-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.crypto-icon {
width: 48px;
height: 48px;
border-radius: 12px;
object-fit: cover;
}
.crypto-name {
font-size: 1.125rem;
font-weight: 700;
color: white;
}
.crypto-symbol {
color: #9ca3af;
font-size: 0.875rem;
}
.crypto-price {
font-size: 1.5rem;
font-weight: 800;
margin-bottom: 0.5rem;
}
.price-change {
font-size: 0.875rem;
font-weight: 600;
}
.price-up {
color: #10b981;
}
.price-down {
color: #ef4444;
}
.crypto-stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
margin-top: 1rem;
}
.stat-label {
color: #9ca3af;
font-size: 0.75rem;
}
.stat-value {
font-weight: 600;
color: white;
}
.sparkline {
height: 40px;
margin-top: 1rem;
}
.watchlist-btn {
background: none;
border: none;
color: #9ca3af;
cursor: pointer;
transition: color 0.3s ease;
}
.watchlist-btn:hover {
color: #3b82f6;
}
.premium-badge {
position: absolute;
top: 1rem;
right: 1rem;
background: linear-gradient(135deg, #fbbf24, #f59e0b);
color: #1f2937;
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
}
.quick-actions {
display: flex;
justify-content: space-between;
margin-top: 1rem;
}
</style>
<div class="crypto-card">
${cryptoData.market_cap_rank <= 10 ? '<div class="premium-badge">Top 10</div>' : ''}
<div class="crypto-header">
<img
src="${cryptoData.image}"
alt="${cryptoData.name}"
class="crypto-icon"
>
<div>
<div class="crypto-name">${cryptoData.name}</div>
<div class="crypto-symbol">${cryptoData.symbol.toUpperCase()}</div>
</div>
</div>
<div class="crypto-price">$${cryptoData.current_price.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</div>
<div class="price-change ${cryptoData.price_change_percentage_24h >= 0 ? 'price-up' : 'price-down'}">
${cryptoData.price_change_percentage_24h >= 0 ? '+' : ''}${cryptoData.price_change_percentage_24h?.toFixed(2) || '0.00'}%
</div>
<div class="crypto-stats">
<div class="stat-label">Market Cap</div>
<div class="stat-value">$${(cryptoData.market_cap / 1000000000).toFixed(2)}B</div>
<div class="stat-label">24h Volume</div>
<div class="stat-value">$${(cryptoData.total_volume / 1000000).toFixed(2)}M</div>
</div>
<div class="sparkline" id="sparkline-${cryptoData.id}"></div>
<div class="quick-actions">
<button class="watchlist-btn">
<i data-feather="star"></i>
</button>
<button class="watchlist-btn">
<i data-feather="bell"></i>
</button>
</div>
</div>
`;
this.setupInteractions();
this.renderSparkline(cryptoData);
}
setupInteractions() {
const card = this.shadowRoot.querySelector('.crypto-card');
const watchlistBtn = this.shadowRoot.querySelector('.watchlist-btn');
watchlistBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.toggleWatchlist();
});
card.addEventListener('click', () => {
this.viewCryptoDetails();
});
}
renderSparkline(cryptoData) {
const sparklineContainer = this.shadowRoot.querySelector('.sparkline');
if (cryptoData.sparkline_in_7d?.price) {
// In a real implementation, you would use a charting library
// For demo, we'll create a simple SVG sparkline
const sparklineData = cryptoData.sparkline_in_7d.price;
const width = 200;
const height = 40;
sparklineContainer.innerHTML = `
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
<polyline
fill="none"
stroke="${cryptoData.price_change_percentage_24h >= 0 ? '#10b981' : '#ef4444'}"
stroke-width="2"
points="${sparklineData.map((price, index) => {
const x = (index / (sparklineData.length - 1)) * width},${height - ((price - Math.min(...sparklineData)) / (Math.max(...sparklineData) - Math.min(...sparklineData)) * height}"
/>
</svg>
`;
}
}
toggleWatchlist() {
const starIcon = this.shadowRoot.querySelector('.watchlist-btn i');
if (starIcon.getAttribute('data-feather') === 'star') {
starIcon.setAttribute('data-feather', 'star');
} else {
starIcon.setAttribute('data-feather', 'star');
}
feather.replace();
}
viewCryptoDetails() {
const cryptoData = JSON.parse(this.getAttribute('data-crypto')));
// Navigate to crypto details page
window.location.href = `/crypto-details.html?id=${cryptoData.id}`;
}
}
customElements.define('crypto-card', CryptoCard);