Dashboards are essential tools for visualizing data and making informed decisions. They provide a snapshot of key metrics and trends at a glance.
In this article, we will explore 10 exemplary dashboards that showcase innovative design and functionality. These examples will inspire you to create your own stunning and effective dashboards.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Subframe's drag-and-drop interface and intuitive, responsive canvas make it easy to create pixel-perfect dashboards every time. Loved by designers and developers alike, Subframe ensures your UI is both stunning and functional.
Start for free and experience the difference today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI design game? With Subframe, you can create pixel-perfect dashboards and UIs in minutes, thanks to our intuitive drag-and-drop editor and beautifully crafted components.
Experience unparalleled efficiency and start designing stunning interfaces immediately. Start for free and bring your vision to life today!
<html> <head> <title>Corporate Performance Dashboard</title> <style> :root { --primary: #2A3F54; --secondary: #4A6491; --accent: #7A9CC6; --light: #F0F3F8; --dark: #1C2B3A; --success: #27AE60; --warning: #E67E22; --danger: #E74C3C; --neutral: #95A5A6; --shadow: rgba(42, 63, 84, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; } body { background: var(--light); color: var(--dark); font-size: 14px; line-height: 1.5; overflow-x: hidden; height: 100vh; width: 100%; padding: 0; margin: 0; } .dashboard { display: grid; grid-template-rows: auto 1fr; height: 100vh; max-width: 700px; margin: 0 auto; overflow: hidden; background: white; box-shadow: 0 0 40px var(--shadow); } .header { background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); color: white; padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; z-index: 10; } .header-left { display: flex; align-items: center; } .logo { font-weight: 700; font-size: 1.2rem; margin-right: 20px; letter-spacing: 0.5px; } .header-nav { display: flex; gap: 15px; } .header-nav a { color: rgba(255, 255, 255, 0.7); text-decoration: none; font-size: 0.9rem; font-weight: 500; transition: all 0.2s ease; position: relative; } .header-nav a.active { color: white; } .header-nav a.active::after { content: ''; position: absolute; bottom: -4px; left: 0; width: 100%; height: 2px; background-color: white; border-radius: 2px; } .header-nav a:hover { color: white; } .profile { display: flex; align-items: center; gap: 10px; cursor: pointer; } .profile-avatar { width: 32px; height: 32px; border-radius: 50%; background: white; display: flex; align-items: center; justify-content: center; color: var(--primary); font-weight: 600; font-size: 14px; } .content { padding: 20px; overflow-y: auto; height: calc(100vh - 66px); } .dashboard-section { margin-bottom: 24px; } .section-header { margin-bottom: 12px; display: flex; justify-content: space-between; align-items: center; } .section-title { font-size: 1rem; font-weight: 600; color: var(--dark); } .period-selector { display: flex; background: var(--light); border-radius: 6px; overflow: hidden; } .period-selector button { border: none; background: transparent; padding: 6px 10px; font-size: 0.75rem; cursor: pointer; color: var(--neutral); transition: all 0.2s ease; } .period-selector button.active { background: white; color: var(--primary); font-weight: 500; box-shadow: 0 2px 5px var(--shadow); } .dashboard-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 16px; margin-bottom: 24px; } .card { background: white; border-radius: 10px; padding: 16px; box-shadow: 0 2px 10px var(--shadow); display: flex; flex-direction: column; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; } .card:hover { transform: translateY(-5px); box-shadow: 0 10px 20px var(--shadow); } .card-title { font-size: 0.8rem; color: var(--neutral); margin-bottom: 8px; } .card-value { font-size: 1.5rem; font-weight: 700; margin-bottom: 10px; } .card-trend { display: flex; align-items: center; font-size: 0.75rem; } .trend-positive { color: var(--success); } .trend-negative { color: var(--danger); } .trend-icon { margin-right: 5px; } .chart-container { background: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 10px var(--shadow); margin-bottom: 24px; position: relative; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .chart-title { font-weight: 600; font-size: 1rem; } .legend { display: flex; gap: 15px; } .legend-item { display: flex; align-items: center; font-size: 0.8rem; color: var(--neutral); } .legend-color { width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; } .insights-section { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } .insight-card { background: white; border-radius: 10px; padding: 16px; box-shadow: 0 2px 10px var(--shadow); } .insight-card h3 { font-size: 0.9rem; margin-bottom: 8px; font-weight: 600; } .insight-card p { font-size: 0.8rem; color: var(--neutral); } .insight-status { display: flex; align-items: center; margin-top: 10px; font-size: 0.8rem; } .status-indicator { width: 8px; height: 8px; border-radius: 50%; margin-right: 5px; } .chart { width: 100%; height: 200px; position: relative; } .bar-container { display: flex; justify-content: space-between; align-items: flex-end; height: 100%; padding-top: 20px; } .bar-group { display: flex; gap: 6px; width: 30px; justify-content: center; } .bar { width: 12px; border-radius: 4px 4px 0 0; transition: height 1s cubic-bezier(0.2, 0.8, 0.2, 1); } .bar1 { background: linear-gradient(to top, var(--primary), var(--secondary)); } .bar2 { background: linear-gradient(to top, #E0E6ED, #CBD2D9); } .grid-lines { position: absolute; width: 100%; height: 100%; top: 0; left: 0; } .grid-line { position: absolute; width: 100%; height: 1px; background-color: rgba(200, 200, 200, 0.2); } .x-labels { display: flex; justify-content: space-between; width: 100%; margin-top: 8px; } .x-label { text-align: center; font-size: 0.7rem; color: var(--neutral); width: 30px; } .analytics-highlights { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 20px; } .highlight-card { background: linear-gradient(135deg, rgba(42, 63, 84, 0.03) 0%, rgba(74, 100, 145, 0.05) 100%); border-radius: 10px; padding: 15px; position: relative; overflow: hidden; cursor: pointer; transition: all 0.3s ease; } .highlight-card:hover { background: linear-gradient(135deg, rgba(42, 63, 84, 0.06) 0%, rgba(74, 100, 145, 0.1) 100%); } .highlight-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .highlight-title { font-size: 0.9rem; font-weight: 600; } .highlight-icon { width: 24px; height: 24px; border-radius: 6px; background: white; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px var(--shadow); } .highlight-value { font-size: 1.2rem; font-weight: 700; } .highlight-description { margin-top: 5px; font-size: 0.75rem; color: var(--neutral); } /* Dropdown Menu */ .dropdown { position: relative; } .dropdown-toggle { background: transparent; border: none; color: white; cursor: pointer; display: flex; align-items: center; gap: 5px; } .dropdown-menu { position: absolute; top: 100%; right: 0; background: white; border-radius: 8px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); width: 160px; z-index: 10; opacity: 0; visibility: hidden; transform: translateY(10px); transition: all 0.3s ease; } .dropdown-menu.show { opacity: 1; visibility: visible; transform: translateY(5px); } .dropdown-item { padding: 10px 15px; color: var(--dark); font-size: 0.85rem; cursor: pointer; display: flex; align-items: center; gap: 8px; } .dropdown-item:hover { background: var(--light); } .dropdown-divider { height: 1px; background: var(--light); margin: 5px 0; } /* Loader animation */ .loading-indicator { position: absolute; top: 0; left: 0; width: 100%; height: 3px; background: linear-gradient(to right, transparent, var(--primary), transparent); animation: loadingAnimation 1.5s infinite; opacity: 0; transition: opacity 0.3s ease; } .loading-indicator.active { opacity: 1; } @keyframes loadingAnimation { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* Tooltip */ .tooltip { position: absolute; background: var(--dark); color: white; padding: 8px 12px; border-radius: 6px; font-size: 0.75rem; pointer-events: none; opacity: 0; transition: opacity 0.2s ease; z-index: 100; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); max-width: 200px; } .tooltip::after { content: ''; position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 6px solid var(--dark); } /* Responsive styles */ @media (max-width: 600px) { .dashboard-cards { grid-template-columns: repeat(2, 1fr); } .header-nav { display: none; } .analytics-highlights { grid-template-columns: 1fr; } .insights-section { grid-template-columns: 1fr; } .chart { height: 150px; } } /* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 0.5s ease forwards; } .delay-1 { animation-delay: 0.1s; } .delay-2 { animation-delay: 0.2s; } .delay-3 { animation-delay: 0.3s; } /* Progress circles */ .progress-circle { position: relative; width: 80px; height: 80px; margin: 0 auto; } .progress-circle svg { transform: rotate(-90deg); } .progress-circle-bg { fill: none; stroke: #f0f0f0; stroke-width: 8; } .progress-circle-value { fill: none; stroke-width: 8; stroke-linecap: round; transition: stroke-dashoffset 1s ease; } .progress-circle-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 20px; font-weight: 700; } .donut-chart { position: relative; width: 100px; height: 100px; } .donut-segment { fill: none; stroke-width: 20; stroke-linecap: round; transition: stroke-dashoffset 1s ease; } </style> </head> <body> <div class="loading-indicator" id="loadingIndicator"></div> <div class="tooltip" id="tooltip"></div> <div class="dashboard"> <header class="header"> <div class="header-left"> <div class="logo">ExecInsight</div> <nav class="header-nav"> <a href="#" class="active">Dashboard</a> <a href="#">Finance</a> <a href="#">Operations</a> <a href="#">Reports</a> </nav> </div> <div class="dropdown"> <button class="dropdown-toggle" id="profileDropdown"> <div class="profile-avatar">JD</div> </button> <div class="dropdown-menu" id="profileMenu"> <div class="dropdown-item"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> <circle cx="12" cy="7" r="4"></circle> </svg> Profile </div> <div class="dropdown-item"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="3"></circle> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> </svg> Settings </div> <div class="dropdown-divider"></div> <div class="dropdown-item"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path> <polyline points="16 17 21 12 16 7"></polyline> <line x1="21" y1="12" x2="9" y2="12"></line> </svg> Logout </div> </div> </div> </header> <main class="content"> <div class="dashboard-section"> <div class="section-header"> <h2 class="section-title">Q2 2023 Performance Overview</h2> <div class="period-selector"> <button>Week</button> <button>Month</button> <button class="active">Quarter</button> <button>Year</button> </div> </div> <div class="dashboard-cards fade-in"> <div class="card" data-metric="revenue"> <div class="card-title">Revenue</div> <div class="card-value">$8.4M</div> <div class="card-trend trend-positive"> <span class="trend-icon">↑</span> 12.8% </div> </div> <div class="card" data-metric="expenses"> <div class="card-title">Expenses</div> <div class="card-value">$5.2M</div> <div class="card-trend trend-negative"> <span class="trend-icon">↑</span> 7.3% </div> </div> <div class="card" data-metric="profit"> <div class="card-title">Net Profit</div> <div class="card-value">$3.2M</div> <div class="card-trend trend-positive"> <span class="trend-icon">↑</span> 18.5% </div> </div> <div class="card" data-metric="margin"> <div class="card-title">Profit Margin</div> <div class="card-value">38.1%</div> <div class="card-trend trend-positive"> <span class="trend-icon">↑</span> 5.2% </div> </div> </div> <div class="chart-container fade-in delay-1"> <div class="chart-header"> <h3 class="chart-title">Quarterly Revenue vs Expenses</h3> <div class="legend"> <div class="legend-item"> <div class="legend-color" style="background: var(--primary);"></div> Revenue </div> <div class="legend-item"> <div class="legend-color" style="background: #CBD2D9;"></div> Expenses </div> </div> </div> <div class="chart"> <div class="grid-lines"> <div class="grid-line" style="top: 0%;"></div> <div class="grid-line" style="top: 25%;"></div> <div class="grid-line" style="top: 50%;"></div> <div class="grid-line" style="top: 75%;"></div> <div class="grid-line" style="top: 100%;"></div> </div> <div class="bar-container"> <div class="bar-group" data-month="July"> <div class="bar bar1" style="height: 0%;"></div> <div class="bar bar2" style="height: 0%;"></div> </div> <div class="bar-group" data-month="Aug"> <div class="bar bar1" style="height: 0%;"></div> <div class="bar bar2" style="height: 0%;"></div> </div> <div class="bar-group" data-month="Sept"> <div class="bar bar1" style="height: 0%;"></div> <div class="bar bar2" style="height: 0%;"></div> </div> <div class="bar-group" data-month="Oct"> <div class="bar bar1" style="height: 0%;"></div> <div class="bar bar2" style="height: 0%;"></div> </div> <div class="bar-group" data-month="Nov"> <div class="bar bar1" style="height: 0%;"></div> <div class="bar bar2" style="height: 0%;"></div> </div> <div class="bar-group" data-month="Dec"> <div class="bar bar1" style="height: 0%;"></div> <div class="bar bar2" style="height: 0%;"></div> </div> </div> <div class="x-labels"> <div class="x-label">July</div> <div class="x-label">Aug</div> <div class="x-label">Sept</div> <div class="x-label">Oct</div> <div class="x-label">Nov</div> <div class="x-label">Dec</div> </div> </div> </div> <div class="analytics-highlights fade-in delay-2"> <div class="highlight-card"> <div class="highlight-header"> <div class="highlight-title">EBITDA</div> <div class="highlight-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2A3F54" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="20" x2="12" y2="10"></line> <line x1="18" y1="20" x2="18" y2="4"></line> <line x1="6" y1="20" x2="6" y2="16"></line> </svg> </div> </div> <div class="highlight-value">$4.7M</div> <div class="highlight-description">Up 15.2% from previous quarter</div> </div> <div class="highlight-card"> <div class="highlight-header"> <div class="highlight-title">Cash Flow</div> <div class="highlight-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2A3F54" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path> </svg> </div> </div> <div class="highlight-value">$3.1M</div> <div class="highlight-description">Operational cash flow stabilizing</div> </div> <div class="highlight-card"> <div class="highlight-header"> <div class="highlight-title">ROI</div> <div class="highlight-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2A3F54" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M2 20h.01"></path> <path d="M7 20v-4"></path> <path d="M12 20v-8"></path> <path d="M17 20v-12"></path> <path d="M22 20v-16"></path> </svg> </div> </div> <div class="highlight-value">21.3%</div> <div class="highlight-description">Above industry average by 4.7%</div> </div> <div class="highlight-card"> <div class="highlight-header"> <div class="highlight-title">Debt Ratio</div> <div class="highlight-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2A3F54" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 4H3a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z"></path> <path d="M16 10a4 4 0 0 1-8 0"></path> </svg> </div> </div> <div class="highlight-value">0.38</div> <div class="highlight-description">Decreased from 0.42 in Q1</div> </div> </div> <div class="insights-section fade-in delay-3"> <div class="insight-card"> <h3>Growth Acceleration</h3> <p>Tech division outperforming forecasts by 17%. Recommend increasing investment in R&D for Q3.</p> <div class="insight-status"> <div class="status-indicator" style="background: var(--success);"></div> High Priority </div> </div> <div class="insight-card"> <h3>Cost Optimization</h3> <p>Supply chain efficiency up 8.2%. Continue negotiating volume discounts with top 3 suppliers.</p> <div class="insight-status"> <div class="status-indicator" style="background: var(--warning);"></div> Medium Priority </div> </div> </div> </div> </main> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Simulate loading const loadingIndicator = document.getElementById('loadingIndicator'); loadingIndicator.classList.add('active'); setTimeout(() => { loadingIndicator.classList.remove('active'); initializeDashboard(); }, 1000); // Profile dropdown functionality const profileDropdown = document.getElementById('profileDropdown'); const profileMenu = document.getElementById('profileMenu'); profileDropdown.addEventListener('click', function(e) { e.stopPropagation(); profileMenu.classList.toggle('show'); }); document.addEventListener('click', function(e) { if (!profileMenu.contains(e.target) && e.target !== profileDropdown) { profileMenu.classList.remove('show'); } }); // Tooltip functionality const tooltip = document.getElementById('tooltip'); const cards = document.querySelectorAll('.card'); cards.forEach(card => { card.addEventListener('mousemove', function(e) { const rect = this.getBoundingClientRect(); const metric = this.getAttribute('data-metric'); let tooltipText = ''; switch(metric) { case 'revenue': tooltipText = 'Total revenue from all business units. 12.8% increase driven by tech division growth.'; break; case 'expenses': tooltipText = 'Overall expenses increased 7.3% due to expansion in APAC region and talent acquisition.'; break; case 'profit': tooltipText = 'Net profit after taxes. 18.5% increase exceeds quarterly target by 3.2%.'; break; case 'margin': tooltipText = 'Profit margin at 38.1% reflects operational efficiency improvements and premium pricing strategy.'; break; } tooltip.textContent = tooltipText; tooltip.style.opacity = '1'; // Position tooltip const tooltipWidth = tooltip.offsetWidth; const tooltipHeight = tooltip.offsetHeight; tooltip.style.left = Math.min(rect.left + (rect.width / 2) - (tooltipWidth / 2), window.innerWidth - tooltipWidth - 10) + 'px'; tooltip.style.top = (rect.top - tooltipHeight - 10) + 'px'; }); card.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; }); }); }); function initializeDashboard() { // Animate the bars in the chart const barGroups = document.querySelectorAll('.bar-group'); const revenueData = [65, 72, 78, 83, 80, 88]; // percentages const expensesData = [50, 53, 58, 62, 57, 63]; // percentages barGroups.forEach((group, index) => { setTimeout(() => { const bars = group.querySelectorAll('.bar'); bars[0].style.height = revenueData[index] + '%'; bars[1].style.height = expensesData[index] + '%'; // Add hover interaction for bar groups group.addEventListener('mouseenter', function() { const month = this.getAttribute('data-month'); const revenueVal = revenueData[index]; const expenseVal = expensesData[index]; const tooltip = document.getElementById('tooltip'); tooltip.innerHTML = ` <strong>${month}</strong><br> Revenue: $${(revenueVal / 100 * 10).toFixed(1)}M<br> Expenses: $${(expenseVal / 100 * 10).toFixed(1)}M `; tooltip.style.opacity = '1'; const rect = this.getBoundingClientRect(); const tooltipWidth = tooltip.offsetWidth; tooltip.style.left = (rect.left + (rect.width / 2) - (tooltipWidth / 2)) + 'px'; tooltip.style.top = (rect.top - tooltip.offsetHeight - 10) + 'px'; }); group.addEventListener('mouseleave', function() { const tooltip = document.getElementById('tooltip'); tooltip.style.opacity = '0'; }); }, index * 100); }); // Period selector functionality const periodButtons = document.querySelectorAll('.period-selector button'); periodButtons.forEach(button => { button.addEventListener('click', function() { // Remove active class from all buttons periodButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Show loading indicator const loadingIndicator = document.getElementById('loadingIndicator'); loadingIndicator.classList.add('active'); // Simulate data refresh setTimeout(() => { loadingIndicator.classList.remove('active'); // Update chart with new "data" const newRevenuePercentages = [ Math.floor(Math.random() * 30) + 60, Math.floor(Math.random() * 30) + 60, Math.floor(Math.random() * 30) + 60, Math.floor(Math.random() * 30) + 60, Math.floor(Math.random() * 30) + 60, Math.floor(Math.random() * 30) + 60 ]; const newExpensesPercentages = [ Math.floor(Math.random
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Healthcare Metrics Dashboard</title> <style> :root { --primary-blue: #4a90e2; --primary-light: #ebf3ff; --secondary-blue: #1c62b3; --accent-teal: #00d4b1; --accent-red: #ff6b6b; --accent-yellow: #ffca58; --accent-purple: #9d65c9; --text-dark: #2c3e50; --text-light: #7f8c8d; --white: #ffffff; --shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background-color: var(--primary-light); color: var(--text-dark); width: 100%; height: 100%; overflow-x: hidden; font-size: 14px; } .dashboard-container { max-width: 700px; height: 700px; margin: 0 auto; padding: 20px; display: grid; grid-template-rows: auto 1fr; gap: 20px; overflow-y: auto; } .header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 15px; border-bottom: 1px solid rgba(74, 144, 226, 0.2); } .header-left { display: flex; align-items: center; } .logo { width: 40px; height: 40px; background-color: var(--primary-blue); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; margin-right: 12px; box-shadow: var(--shadow); } .title h1 { font-size: 18px; font-weight: 600; color: var(--text-dark); } .title p { font-size: 12px; color: var(--text-light); } .header-right { display: flex; align-items: center; gap: 15px; } .date-selector { display: flex; align-items: center; background-color: var(--white); border-radius: 6px; padding: 6px 12px; box-shadow: var(--shadow); cursor: pointer; transition: var(--transition); } .date-selector:hover { transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0, 0, 0, 0.1); } .date-selector i { margin-right: 5px; color: var(--primary-blue); } .notification-bell { position: relative; width: 36px; height: 36px; background-color: var(--white); border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow); cursor: pointer; transition: var(--transition); } .notification-bell:hover { transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0, 0, 0, 0.1); } .notification-dot { position: absolute; top: 8px; right: 8px; width: 8px; height: 8px; background-color: var(--accent-red); border-radius: 50%; } .dashboard-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto auto 1fr; gap: 16px; height: calc(100% - 80px); } .card { background-color: var(--white); border-radius: 12px; box-shadow: var(--shadow); padding: 16px; transition: var(--transition); position: relative; overflow: hidden; } .card:hover { transform: translateY(-3px); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); } .large-card { grid-column: span 3; display: flex; flex-direction: column; } .medium-card { grid-column: span 2; display: flex; flex-direction: column; } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; } .card-title { font-size: 14px; font-weight: 600; color: var(--text-dark); } .card-subtitle { font-size: 12px; color: var(--text-light); margin-top: 2px; } .card-actions { display: flex; gap: 8px; } .filter-btn { background-color: var(--primary-light); color: var(--primary-blue); border: none; border-radius: 6px; padding: 4px 8px; font-size: 12px; cursor: pointer; transition: var(--transition); } .filter-btn:hover { background-color: var(--primary-blue); color: var(--white); } .stat-large { font-size: 28px; font-weight: 700; color: var(--text-dark); margin-top: 4px; } .stat-card { display: flex; align-items: center; padding: 12px; } .stat-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; margin-right: 12px; flex-shrink: 0; } .up-icon { background-color: rgba(0, 212, 177, 0.15); color: var(--accent-teal); } .down-icon { background-color: rgba(255, 107, 107, 0.15); color: var(--accent-red); } .neutral-icon { background-color: rgba(74, 144, 226, 0.15); color: var(--primary-blue); } .stat-value { font-size: 18px; font-weight: 600; } .stat-label { font-size: 12px; color: var(--text-light); margin-top: 2px; } .trend-label { display: flex; align-items: center; margin-top: 4px; font-size: 12px; font-weight: 500; } .trend-up { color: var(--accent-teal); } .trend-down { color: var(--accent-red); } .alert-card { border-left: 4px solid var(--accent-red); } .chart-container { flex-grow: 1; width: 100%; height: 100%; min-height: 120px; position: relative; } #occupancy-chart, #admission-chart, #wait-time-chart { width: 100%; height: 100%; } .tabs { display: flex; margin-bottom: 16px; border-bottom: 1px solid rgba(74, 144, 226, 0.2); } .tab { padding: 8px 16px; font-size: 14px; cursor: pointer; border-bottom: 2px solid transparent; transition: var(--transition); } .tab.active { border-bottom: 2px solid var(--primary-blue); color: var(--primary-blue); font-weight: 500; } .department-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; max-height: 180px; overflow-y: auto; } .department-item { display: flex; justify-content: space-between; align-items: center; padding: 8px; border-radius: 6px; transition: var(--transition); } .department-item:hover { background-color: var(--primary-light); } .department-name { font-size: 13px; } .department-value { font-weight: 600; font-size: 14px; } .capacity-bar { height: 6px; width: 80px; background-color: rgba(74, 144, 226, 0.2); border-radius: 3px; overflow: hidden; margin-left: 8px; } .capacity-fill { height: 100%; border-radius: 3px; } .capacity-low { background-color: var(--accent-teal); } .capacity-medium { background-color: var(--accent-yellow); } .capacity-high { background-color: var(--accent-red); } .capacity-wrapper { display: flex; align-items: center; } .alert-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; } .alert-item { display: flex; align-items: center; padding: 8px; border-radius: 6px; background-color: rgba(255, 107, 107, 0.1); border-left: 3px solid var(--accent-red); } .alert-icon { background-color: var(--accent-red); color: white; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-right: 12px; } .alert-text { font-size: 13px; flex-grow: 1; } .alert-time { font-size: 12px; color: var(--text-light); } .legend { display: flex; justify-content: center; gap: 16px; margin-top: 8px; } .legend-item { display: flex; align-items: center; font-size: 12px; color: var(--text-light); } .legend-color { width: 12px; height: 12px; border-radius: 2px; margin-right: 6px; } .tooltip { position: absolute; background-color: rgba(255, 255, 255, 0.95); padding: 10px; border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); pointer-events: none; opacity: 0; transition: opacity 0.2s; z-index: 10; max-width: 200px; } /* Animation Classes */ .pulse { animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .fade-in { opacity: 0; animation: fadeIn 0.5s forwards; } @keyframes fadeIn { to { opacity: 1; } } .slide-in { transform: translateY(20px); opacity: 0; animation: slideIn 0.5s forwards; } @keyframes slideIn { to { transform: translateY(0); opacity: 1; } } /* Responsive styles */ @media (max-width: 650px) { .dashboard-grid { grid-template-columns: 1fr; } .large-card, .medium-card { grid-column: span 1; } .header { flex-direction: column; align-items: flex-start; gap: 10px; } .header-right { width: 100%; justify-content: space-between; } } /* Shimmer effect for loading states */ .shimmer { position: relative; overflow: hidden; background: #f6f7f8; } .shimmer::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,0) 100%); animation: shimmer 1.5s infinite; } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* Custom scrollbar */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: var(--primary-light); border-radius: 3px; } ::-webkit-scrollbar-thumb { background: var(--primary-blue); border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { background: var(--secondary-blue); } </style> </head> <body> <div class="dashboard-container"> <div class="header slide-in" style="animation-delay: 0.1s"> <div class="header-left"> <div class="logo"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 12h-4l-3 9L9 3l-3 9H2"></path> </svg> </div> <div class="title"> <h1>St. Elizabeth Medical Center</h1> <p>Healthcare Metrics Dashboard</p> </div> </div> <div class="header-right"> <div class="date-selector"> <i> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> <line x1="16" y1="2" x2="16" y2="6"></line> <line x1="8" y1="2" x2="8" y2="6"></line> <line x1="3" y1="10" x2="21" y2="10"></line> </svg> </i> <span>May 15 - May 21, 2023</span> </div> <div class="notification-bell"> <div class="notification-dot pulse"></div> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#4a90e2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path> <path d="M13.73 21a2 2 0 0 1-3.46 0"></path> </svg> </div> </div> </div> <div class="dashboard-grid"> <!-- Hospital Capacity Stats --> <div class="card slide-in" style="animation-delay: 0.2s"> <div class="card-header"> <div> <div class="card-title">Bed Occupancy</div> <div class="card-subtitle">Current status</div> </div> </div> <div class="stat-large">86%</div> <div class="trend-label trend-up"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 4px;"> <polyline points="18 15 12 9 6 15"></polyline> </svg> 7% from last week </div> </div> <!-- Average Patient Wait Time --> <div class="card slide-in" style="animation-delay: 0.3s"> <div class="card-header"> <div> <div class="card-title">Avg. Wait Time</div> <div class="card-subtitle">Emergency Department</div> </div> </div> <div class="stat-large">42 min</div> <div class="trend-label trend-down"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 4px;"> <polyline points="6 9 12 15 18 9"></polyline> </svg> 12% from last week </div> </div> <!-- Critical Alerts --> <div class="card alert-card slide-in" style="animation-delay: 0.4s"> <div class="card-header"> <div> <div class="card-title">Critical Alerts</div> <div class="card-subtitle">Needs attention</div> </div> </div> <div class="stat-large">3</div> <div class="trend-label" style="color: var(--accent-red);"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 4px;"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="8" x2="12" y2="12"></line> <line x1="12" y1="16" x2="12.01" y2="16"></line> </svg> Click to view </div> </div> <!-- Hospital Occupancy Chart --> <div class="card large-card slide-in" style="animation-delay: 0.5s"> <div class="card-header"> <div> <div class="card-title">Hospital Occupancy Trend</div> <div class="card-subtitle">Past 7 days</div> </div> <div class="card-actions"> <button class="filter-btn">Daily</button> <button class="filter-btn">Weekly</button> </div> </div> <div class="chart-container"> <canvas id="occupancy-chart"></canvas> </div> <div class="legend"> <div class="legend-item"> <div class="legend-color" style="background-color: #4a90e2;"></div> <span>Actual Occupancy</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: #ff6b6b;"></div> <span>Critical Threshold</span> </div> </div> </div> <!-- Admission & Discharge Chart --> <div class="card medium-card slide-in" style="animation-delay: 0.6s"> <div class="card-header"> <div> <div class="card-title">Admissions & Discharges</div> <div class="card-subtitle">Past 7 days</div> </div> </div> <div class="chart-container"> <canvas id="admission-chart"></canvas> </div> </div> <!-- Department Capacity --> <div class="card slide-in" style="animation-delay: 0.7s"> <div class="card-header"> <div> <div class="card-title">Department Capacity</div> <div class="card-subtitle">Current status</div> </div> </div> <div class="department-list"> <div class="department-item"> <div class="department-name">ICU</div> <div class="capacity-wrapper"> <div class="department-value">92%</div> <div class="capacity-bar"> <div class="capacity-fill capacity-high" style="width: 92%"></div> </div> </div> </div> <div class="department-item"> <div class="department-name">Emergency</div> <div class="capacity-wrapper"> <div class="department-value">88%</div> <div class="capacity-bar"> <div class="capacity-fill capacity-high" style="width: 88%"></div> </div> </div> </div> <div class="department-item"> <div class="department-name">Surgery</div> <div class="capacity-wrapper"> <div class="department-value">75%</div> <div class="capacity-bar"> <div class="capacity-fill capacity-medium" style="width: 75%"></div> </div> </div> </div> <div class="department-item"> <div class="department-name">Pediatrics</div> <div class="capacity-wrapper"> <div class="department-value">63%</div> <div class="capacity-bar"> <div class="capacity-fill capacity-medium" style="width: 63%"></div> </div> </div> </div> <div class="department-item"> <div class="department-name">Maternity</div> <div class="capacity-wrapper"> <div class="department-value">52%</div> <div class="capacity-bar"> <div class="capacity-fill capacity-low" style="width: 52%"></div> </div> </div> </div> </div> </div> <!-- Wait Time Metrics --> <div class="card medium-card slide-in" style="animation-delay: 0.8s"> <div class="card-header"> <div> <div class="card-title">Patient Wait Times</div> <div class="card-subtitle">By department</div> </div> </div> <div class="tabs"> <div class="tab active">Emergency</div> <div class="tab">Outpatient</div> <div class="tab">Radiology</div> </div> <div class="chart-container"> <canvas id="wait-time-chart"></canvas> </div> </div> <!-- Critical Alerts --> <div class="card slide-in" style="animation-delay: 0.9s"> <div class="card-header"> <div> <div class="card-title">Critical Alerts</div> <div class="card-subtitle">Today's issues</div> </div> </div> <div class="alert-list"> <div class="alert-item"> <div class="alert-icon">!</div> <div class="alert-text">ICU approaching full capacity (92%)</div> <div class="alert-time">2h ago</div> </div> <div class="alert-item"> <div class="alert-icon">!</div> <div class="alert-text">Emergency staffing shortage - 3 nurses needed</div> <div class="alert-time">4h ago</div> </div> <div class="alert-item"> <div class="alert-icon">!</div> <div class="alert-text">CT Scanner 2 maintenance required</div> <div class="alert-time">8h ago</div> </div> </div> </div> </div> </div> <div class="tooltip" id="tooltip"></div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> // Initialize after a slight delay to ensure DOM is ready setTimeout(() => { // Set up Occupancy Chart const occupancyCtx = document.getElementById('occupancy-chart').getContext('2d'); const occupancyChart = new Chart(occupancyCtx, { type: 'line', data: { labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], datasets: [ { label: 'Occupancy Rate', data: [78, 82, 79, 84, 86, 83, 86], borderColor: '#4a90e2', backgroundColor: 'rgba(74, 144, 226, 0.1)', borderWidth: 2, tension: 0.4, fill: true, pointBackgroundColor: '#ffffff', pointBorderColor: '#4a90e2', pointBorderWidth: 2, pointRadius: 4, pointHoverRadius: 6 }, { label: 'Critical Threshold', data: [90, 90, 90, 90, 90, 90, 90], borderColor: '#ff6b6b', borderWidth: 2, borderDash: [5, 5], fill: false, pointRadius: 0 } ] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { mode: 'index', intersect: false, backgroundColor: 'rgba(255, 255, 255, 0.95)', titleColor: '#2c3e50', bodyColor: '#7f8c8d', borderColor: 'rgba(74, 144, 226, 0.3)', borderWidth: 1, caretPadding: 10, displayColors: true, boxWidth: 10, boxHeight: 10, padding: 10, boxPadding: 3, callbacks: { title: (tooltipItems) => { return `${tooltipItems[0].label}, 2023`; }, label: (context) => { if (context.dataset.label === 'Critical Threshold') { return `Critical Threshold: ${context.raw}%`; } return `Occupancy Rate: ${context.raw}%`; } } } }, scales: { x: { grid: { display: false }, ticks: { color: '#7f8c8d' } }, y: { beginAtZero: true, max: 100, grid: { color: 'rgba(74, 144, 226, 0.1)' }, ticks: { color: '#7f8c8d', callback: (value) => `${value}%` } } } } }); // Set up Admission Chart const admissionCtx = document.getElementById('admission-chart').getContext('2d'); const admissionChart = new Chart(admissionCtx, { type: 'bar', data: { labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], datasets: [ { label: 'Admissions', data: [42, 38, 45, 39, 41, 36, 43], backgroundColor: 'rgba(74, 144, 226, 0.7)', borderRadius: 4 }, { label: 'Discharges', data: [38, 35, 40, 36, 39, 41, 37], backgroundColor: 'rgba(0, 212, 177, 0.7)', borderRadius: 4 } ] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top', labels: { boxWidth: 12, usePointStyle: true, pointStyle: 'rectRounded', color: '#7f8c8d', font: { size: 11 } } }, tooltip: { backgroundColor: 'rgba(255, 255, 255, 0.95)', titleColor: '#2c3e50', bodyColor: '#7f8c8d', borderColor: 'rgba(74, 144, 226, 0.3)', borderWidth: 1 } }, scales: { x: { grid: { display: false }, ticks: { color: '#7f8c8d' } }, y: { beginAtZero: true, grid: { color: 'rgba(74, 144, 226, 0.1)' }, ticks: { color: '#7f8c8d' } } } } }); // Set up Wait Time Chart const waitTimeCtx = document.getElementById('wait-time-chart').getContext('2d'); const waitTimeChart = new Chart(waitTimeCtx, { type: 'line', data: { labels: ['6 AM', '9 AM', '12 PM', '3 PM', '6 PM', '9 PM', '12 AM'], datasets: [ { label: 'Wait Time (minutes)', data: [28, 45, 52, 48, 62, 42, 30], fill: true, borderColor: '#9d65c9', backgroundColor: 'rgba(157, 101, 201, 0.1)', tension: 0.4, pointBackgroundColor: '#ffffff', pointBorderColor: '#9d65c9', pointBorderWidth: 2, pointRadius: 3, pointHoverRadius: 5 } ] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { x: { grid: { display: false }, ticks: { color: '#7f8c8d', font: { size: 10 } } }, y: { beginAtZero: true, grid: { color: 'rgba(74, 144, 226, 0.1)' }, ticks: { color: '#7f8c8d', callback: (value) => `${value} min` } } } } }); // Tab switching const tabs = document.querySelectorAll('.tab'); tabs.forEach(tab => { tab.addEventListener('click', () => { tabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); // Update chart data based on selected tab if (tab.textContent === 'Emergency') { waitTimeChart.data.datasets[0].data = [28, 45, 52, 48, 62, 42, 30]; waitTimeChart.data.datasets[0].borderColor = '#9d65c9'; waitTimeChart.data.datasets[0].backgroundColor = 'rgba(157, 101, 201, 0.1)'; } else if (tab.textContent === 'Outpatient') { waitTimeChart.data.datasets[0].data = [15, 22, 35, 42, 38, 25, 18]; waitTimeChart.data.datasets[0].borderColor = '#4a90e2'; waitTimeChart.data.datasets[0].backgroundColor = 'rgba(74, 144, 226, 0.1)'; } else if (tab.textContent === 'Radiology') { waitTimeChart.data.datasets[0].data = [20, 32, 45, 38, 30, 25, 15]; waitTimeChart.data.datasets[0].borderColor = '#00d4b1'; waitTimeChart.data.datasets[0].backgroundColor = 'rgba(0, 212, 177, 0.1)'; } waitTimeChart.update(); }); }); // Interactive elements const departmentItems = document.querySelectorAll('.department-item'); departmentItems.forEach(item => { item.addEventListener('mouseenter', () => { item.style.backgroundColor = 'var(--primary-light)'; }); item.addEventListener('mouseleave', () => { item.style.backgroundColor = ''; }); }); const alertItems = document.querySelectorAll('.alert-item'); alertItems.forEach(item => { item.addEventListener('mouseenter', () => { item.style.transform = 'translateX(5px)'; }); item.addEventListener('mouseleave', () => { item.style.transform = ''; }); }); // Filter buttons const filterBtns = document.querySelectorAll('.filter-btn'); filterBtns.forEach(btn => { btn.addEventListener('click', () => { filterBtns.forEach(b => b.style.backgroundColor = 'var(--primary-light)'); filterBtns.forEach(b => b.style.color = 'var(--primary-blue)'); btn.style.backgroundColor = 'var(--primary-blue)'; btn.style.color = 'var(--white)'; // Update chart data based on filter if (btn.textContent === 'Daily') { occupancyChart.data.labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; occupancyChart.data.datasets[0].data = [78, 82, 79, 84, 86, 83,
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>E-commerce Analytics Dashboard</title> <style> :root { --primary: #4a6cff; --secondary: #7d57ff; --accent: #ff5e87; --accent-light: #ff9eb6; --dark: #1c2033; --gray-dark: #383c53; --gray-medium: #6e7191; --gray-light: #e4e5f0; --white: #ffffff; --success: #28cc8b; --warning: #ffc547; --danger: #f25767; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background-color: #f8f9fc; color: var(--dark); width: 100%; height: 700px; overflow: hidden; } .dashboard { display: grid; grid-template-columns: 220px 1fr; grid-template-rows: auto 1fr; grid-template-areas: "sidebar header" "sidebar main"; width: 100%; height: 100%; } .sidebar { grid-area: sidebar; background: linear-gradient(180deg, var(--primary) 0%, var(--secondary) 100%); color: var(--white); padding: 24px 16px; display: flex; flex-direction: column; height: 100%; overflow-y: auto; box-shadow: 5px 0 15px rgba(0, 0, 0, 0.05); z-index: 10; } .sidebar-logo { font-size: 1.5rem; font-weight: 800; margin-bottom: 2.5rem; display: flex; align-items: center; gap: 10px; } .sidebar-logo svg { width: 28px; height: 28px; } .sidebar-nav { list-style-type: none; margin-top: 1rem; } .sidebar-nav-item { margin-bottom: 0.5rem; border-radius: 8px; transition: all 0.2s ease; } .sidebar-nav-item.active { background-color: rgba(255, 255, 255, 0.15); } .sidebar-nav-item:hover:not(.active) { background-color: rgba(255, 255, 255, 0.1); } .sidebar-nav-link { display: flex; align-items: center; padding: 12px 16px; text-decoration: none; color: var(--white); font-weight: 500; font-size: 0.95rem; gap: 12px; } .sidebar-nav-link svg { width: 20px; height: 20px; } .section-title { font-size: 0.8rem; text-transform: uppercase; font-weight: 600; letter-spacing: 1px; color: rgba(255, 255, 255, 0.6); margin: 1.5rem 0 0.8rem 1rem; } .header { grid-area: header; padding: 16px 32px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--gray-light); background-color: var(--white); } .page-title { font-size: 1.4rem; font-weight: 700; color: var(--dark); } .header-actions { display: flex; gap: 20px; align-items: center; } .date-range { display: flex; align-items: center; gap: 8px; padding: 8px 16px; background-color: var(--gray-light); border-radius: 6px; font-size: 0.9rem; font-weight: 500; cursor: pointer; transition: all 0.2s ease; } .date-range:hover { background-color: #daddec; } .profile { display: flex; align-items: center; gap: 12px; cursor: pointer; } .profile-avatar { width: 38px; height: 38px; border-radius: 50%; background-color: var(--accent); display: flex; align-items: center; justify-content: center; color: var(--white); font-weight: 600; font-size: 1rem; } .profile-name { font-size: 0.9rem; font-weight: 600; } .main { grid-area: main; padding: 24px 32px; overflow-y: auto; height: 100%; } .stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 24px; } .stat-card { background-color: var(--white); border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); transition: transform 0.2s ease, box-shadow 0.2s ease; cursor: pointer; position: relative; overflow: hidden; } .stat-card:hover { transform: translateY(-5px); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } .stat-card-title { font-size: 0.85rem; font-weight: 600; color: var(--gray-medium); margin-bottom: 8px; } .stat-card-value { font-size: 1.8rem; font-weight: 700; margin-bottom: 8px; display: flex; align-items: flex-end; gap: 8px; } .stat-card-trend { font-size: 0.8rem; font-weight: 600; padding: 4px 8px; border-radius: 4px; display: inline-flex; align-items: center; gap: 4px; } .trend-up { background-color: rgba(40, 204, 139, 0.1); color: var(--success); } .trend-down { background-color: rgba(242, 87, 103, 0.1); color: var(--danger); } .stat-card::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: linear-gradient(90deg, var(--accent) 0%, var(--primary) 100%); transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; } .stat-card:hover::after { transform: scaleX(1); } .charts-row { display: grid; grid-template-columns: 2fr 1fr; gap: 24px; margin-bottom: 24px; } .chart-card { background-color: var(--white); border-radius: 12px; padding: 24px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); display: flex; flex-direction: column; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .chart-title { font-size: 1.1rem; font-weight: 700; } .chart-options { display: flex; gap: 8px; } .chart-option { padding: 6px 12px; border-radius: 6px; font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; background-color: var(--gray-light); color: var(--gray-medium); } .chart-option.active { background-color: var(--primary); color: var(--white); } .chart-content { flex: 1; position: relative; min-height: 200px; } .sales-chart-container { width: 100%; height: 200px; } .segment-list { flex: 1; overflow-y: auto; } .segment-item { display: flex; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid var(--gray-light); } .segment-item:last-child { border-bottom: none; } .segment-info { display: flex; flex-direction: column; gap: 4px; } .segment-name { font-size: 0.9rem; font-weight: 600; } .segment-count { font-size: 0.8rem; color: var(--gray-medium); } .segment-value { font-size: 1rem; font-weight: 700; } .segments-chart-container { width: 100%; height: 200px; } .bottom-row { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-bottom: 24px; } .product-list { flex: 1; overflow-y: auto; margin-top: 16px; } .product-item { display: grid; grid-template-columns: 50px 1fr auto; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--gray-light); gap: 16px; } .product-item:last-child { border-bottom: none; } .product-image { width: 50px; height: 50px; border-radius: 8px; background-size: cover; background-position: center; } .product-info { display: flex; flex-direction: column; gap: 4px; } .product-name { font-size: 0.9rem; font-weight: 600; } .product-category { font-size: 0.8rem; color: var(--gray-medium); } .product-sales { font-size: 1rem; font-weight: 700; } .performance-markers { display: flex; gap: 16px; margin-top: 16px; } .marker { display: flex; flex-direction: column; align-items: center; flex: 1; padding: 16px; background-color: var(--gray-light); border-radius: 8px; transition: all 0.2s ease; cursor: pointer; } .marker:hover { background-color: #daddec; } .marker-value { font-size: 1.4rem; font-weight: 700; margin-bottom: 4px; } .marker-label { font-size: 0.8rem; color: var(--gray-medium); text-align: center; } .traffic-sources-container { width: 100%; height: 180px; margin-top: 16px; } /* Tooltip styles */ .tooltip { position: absolute; background-color: var(--dark); color: var(--white); padding: 10px; border-radius: 6px; font-size: 0.85rem; pointer-events: none; opacity: 0; transition: opacity 0.2s ease; z-index: 100; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); max-width: 200px; } .tooltip-title { font-weight: 600; margin-bottom: 5px; } .tooltip-value { font-weight: 500; } /* Notification badge */ .badge { position: absolute; top: -5px; right: -5px; background-color: var(--accent); color: white; border-radius: 50%; width: 18px; height: 18px; font-size: 0.7rem; display: flex; align-items: center; justify-content: center; font-weight: 600; box-shadow: 0 2px 5px rgba(242, 87, 103, 0.3); animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(242, 87, 103, 0.7); } 70% { box-shadow: 0 0 0 8px rgba(242, 87, 103, 0); } 100% { box-shadow: 0 0 0 0 rgba(242, 87, 103, 0); } } /* Responsive design */ @media (max-width: 992px) { .stats-grid { grid-template-columns: repeat(2, 1fr); } .charts-row, .bottom-row { grid-template-columns: 1fr; } } @media (max-width: 768px) { .dashboard { grid-template-columns: 1fr; grid-template-areas: "header" "main"; } .sidebar { display: none; } } /* Animation and transitions */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 0.5s ease forwards; } .fade-in-delay-1 { animation: fadeIn 0.5s ease 0.1s forwards; opacity: 0; } .fade-in-delay-2 { animation: fadeIn 0.5s ease 0.2s forwards; opacity: 0; } .fade-in-delay-3 { animation: fadeIn 0.5s ease 0.3s forwards; opacity: 0; } .fade-in-delay-4 { animation: fadeIn 0.5s ease 0.4s forwards; opacity: 0; } /* Custom donut progress */ .donut-chart { width: 100px; height: 100px; position: relative; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto; } .donut-segment { position: absolute; width: 100%; height: 100%; border-radius: 50%; clip: rect(0px, 100px, 100px, 50px); } .donut-segment.clip-auto { clip: auto; } .donut-fill { position: absolute; width: 100%; height: 100%; border-radius: 50%; clip: rect(0px, 50px, 100px, 0px); transform: rotate(0deg); transition: transform 1s ease-in-out; } .donut-inner { position: absolute; width: 70px; height: 70px; background-color: white; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; } .donut-percent { font-size: 1.2rem; font-weight: 700; } .donut-label { font-size: 0.7rem; color: var(--gray-medium); } /* Fancy toggle switch */ .toggle-switch { position: relative; display: inline-block; width: 40px; height: 22px; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--gray-light); transition: .4s; border-radius: 22px; } .toggle-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 2px; bottom: 2px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .toggle-slider { background-color: var(--primary); } input:checked + .toggle-slider:before { transform: translateX(18px); } .table-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .table-actions { display: flex; gap: 12px; align-items: center; } .download-btn { display: flex; align-items: center; gap: 6px; padding: 8px 16px; background-color: var(--white); color: var(--primary); border: 1px solid var(--primary); border-radius: 6px; font-size: 0.85rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; } .download-btn:hover { background-color: var(--primary); color: var(--white); } .search-wrapper { position: relative; display: flex; align-items: center; } .search-input { padding: 8px 16px 8px 36px; border-radius: 6px; border: 1px solid var(--gray-light); font-size: 0.85rem; width: 200px; transition: all 0.2s ease; background-color: var(--white); } .search-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(74, 108, 255, 0.1); width: 250px; } .search-icon { position: absolute; left: 12px; color: var(--gray-medium); pointer-events: none; } /* Progress bar for loading data */ .progress-container { width: 100%; height: 4px; position: absolute; top: 0; left: 0; overflow: hidden; background-color: var(--gray-light); z-index: 1000; opacity: 0; transition: opacity 0.3s ease; } .progress-bar { height: 100%; width: 0; background: linear-gradient(90deg, var(--primary) 0%, var(--accent) 100%); transition: width 0.5s ease; } /* Custom scrollbar */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: var(--gray-light); border-radius: 4px; } ::-webkit-scrollbar-thumb { background: var(--gray-medium); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: var(--primary); } /* Notification panel styles */ .notification-panel { position: absolute; top: 60px; right: 32px; width: 320px; background-color: var(--white); border-radius: 12px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); z-index: 100; opacity: 0; transform: translateY(-10px); pointer-events: none; transition: opacity 0.3s ease, transform 0.3s ease; } .notification-panel.active { opacity: 1; transform: translateY(0); pointer-events: all; } .notification-header { padding: 16px; border-bottom: 1px solid var(--gray-light); display: flex; justify-content: space-between; align-items: center; } .notification-title { font-size: 1rem; font-weight: 600; } .notification-list { max-height: 320px; overflow-y: auto; } .notification-item { padding: 16px; border-bottom: 1px solid var(--gray-light); cursor: pointer; transition: background-color 0.2s ease; } .notification-item:hover { background-color: rgba(74, 108, 255, 0.05); } .notification-item-header { display: flex; justify-content: space-between; margin-bottom: 6px; } .notification-item-title { font-size: 0.9rem; font-weight: 600; } .notification-item-time { font-size: 0.75rem; color: var(--gray-medium); } .notification-item-content { font-size: 0.85rem; color: var(--gray-dark); margin-bottom: 8px; } .notification-item-action { font-size: 0.8rem; color: var(--primary); font-weight: 600; } .notification-footer { padding: 12px; text-align: center; font-size: 0.85rem; color: var(--primary); font-weight: 600; border-top: 1px solid var(--gray-light); cursor: pointer; transition: background-color 0.2s ease; } .notification-footer:hover { background-color: rgba(74, 108, 255, 0.05); } .unread-indicator { width: 8px; height: 8px; background-color: var(--primary); border-radius: 50%; margin-right: 8px; } </style> </head> <body> <div class="dashboard"> <div class="progress-container"> <div class="progress-bar"></div> </div> <aside class="sidebar"> <div class="sidebar-logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon> <polyline points="2 17 12 22 22 17"></polyline> <polyline points="2 12 12 17 22 12"></polyline> </svg> <span>ShopMetrics</span> </div> <ul class="sidebar-nav"> <li class="sidebar-nav-item active"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="7" height="7"></rect> <rect x="14" y="3" width="7" height="7"></rect> <rect x="14" y="14" width="7" height="7"></rect> <rect x="3" y="14" width="7" height="7"></rect> </svg> Dashboard </a> </li> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline> <path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path> </svg> Products </a> </li> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path> <line x1="3" y1="6" x2="21" y2="6"></line> <path d="M16 10a4 4 0 0 1-8 0"></path> </svg> Orders <div class="badge">5</div> </a> </li> <div class="section-title">Analytics</div> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21.21 15.89A10 10 0 1 1 8 2.83"></path> <path d="M22 12A10 10 0 0 0 12 2v10z"></path> </svg> Sales </a> </li> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> <circle cx="12" cy="7" r="4"></circle> </svg> Customers </a> </li> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="2" y1="12" x2="22" y2="12"></line> <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path> </svg> Traffic </a> </li> <div class="section-title">System</div> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="3"></circle> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> </svg> Settings </a> </li> <li class="sidebar-nav-item"> <a href="#" class="sidebar-nav-link"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path> <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path> </svg> API Access </a> </li> </ul> </aside> <header class="header"> <h1 class="page-title">Sales Analytics</h1> <div class="header-actions"> <div class="date-range"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> <line x1="16" y1="2" x2="16" y2="6"></line> <line x1="8" y1="2" x2="8" y2="6"></line> <line x1="3" y1="10" x2="21" y2="10"></line> </svg> <span>Last 30 days</span> </div> <div class="profile" id="profile-trigger"> <div class="profile-avatar">JD</div> <div class="profile-name">John Doe</div> </div> </div> </header> <main class="main"> <div class="stats-grid"> <div class="stat-card fade-in"> <div class="stat-card-title">Total Revenue</div> <div class="stat-card-value">$142,845</div> <div class="stat-card-trend trend-up"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> +18.2% </div> </div> <div class="stat-card fade-in-delay-1"> <div class="stat-card-title">Orders</div> <div class="stat-card-value">2,589</div> <div class="stat-card-trend trend-up"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> +7.3% </div> </div> <div class="stat-card fade-in-delay-2"> <div class="stat-card-title">Average Order Value</div> <div class="stat-card-value">$55.17</div> <div class="stat-card-trend trend-up"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> +3.1% </div> </div> <div class="stat-card fade-in-delay-3"> <div class="stat-card-title">Conversion Rate</div> <div class="stat-card-value">4.6%</div> <div class
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Project Management Dashboard</title> <style> :root { --primary: #3498db; --secondary: #2ecc71; --accent: #e74c3c; --warning: #f39c12; --dark: #34495e; --light: #ecf0f1; --shadow: 0 4px 8px rgba(0, 0, 0, 0.1); --transition: all 0.3s ease; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f5f7fa; color: #333; height: 700px; width: 700px; overflow: hidden; } .dashboard { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: auto 1fr; grid-template-areas: "sidebar header" "sidebar main"; height: 100%; width: 100%; overflow: hidden; } .sidebar { grid-area: sidebar; background-color: var(--dark); color: white; padding: 20px; transition: var(--transition); display: flex; flex-direction: column; z-index: 100; } .sidebar-header { display: flex; align-items: center; margin-bottom: 30px; } .logo { width: 40px; height: 40px; background-color: var(--primary); border-radius: 8px; position: relative; overflow: hidden; } .logo::before, .logo::after { content: ""; position: absolute; background-color: white; } .logo::before { width: 60%; height: 10px; top: 15px; left: 8px; border-radius: 5px; } .logo::after { width: 10px; height: 60%; top: 8px; left: 15px; border-radius: 5px; } .brand-name { margin-left: 10px; font-weight: 600; letter-spacing: 0.5px; } .nav-menu { list-style: none; margin-top: 20px; } .nav-item { margin-bottom: 15px; padding: 10px; border-radius: 6px; cursor: pointer; display: flex; align-items: center; transition: var(--transition); } .nav-item:hover, .nav-item.active { background-color: rgba(255, 255, 255, 0.1); } .nav-item.active { background-color: var(--primary); } .nav-icon { margin-right: 10px; font-size: 18px; width: 20px; text-align: center; } .header { grid-area: header; padding: 15px 25px; background-color: white; display: flex; justify-content: space-between; align-items: center; box-shadow: var(--shadow); z-index: 90; } .search-bar { position: relative; width: 300px; } .search-bar input { width: 100%; padding: 10px 15px 10px 40px; border: none; background-color: var(--light); border-radius: 20px; font-size: 14px; outline: none; transition: var(--transition); } .search-bar input:focus { box-shadow: 0 0 0 2px var(--primary); } .search-icon { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: #888; } .user-profile { display: flex; align-items: center; cursor: pointer; } .avatar { width: 40px; height: 40px; border-radius: 50%; background-color: var(--primary); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; margin-right: 10px; } .user-info { display: flex; flex-direction: column; } .username { font-weight: 600; font-size: 14px; } .user-role { font-size: 12px; color: #888; } .main { grid-area: main; padding: 20px; overflow-y: auto; height: 100%; } .dashboard-title { font-size: 24px; font-weight: 600; margin-bottom: 20px; } .widgets-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 25px; } .widget { background-color: white; border-radius: 10px; padding: 20px; box-shadow: var(--shadow); transition: var(--transition); height: 120px; display: flex; flex-direction: column; justify-content: space-between; } .widget:hover { transform: translateY(-5px); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); } .widget-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .widget-title { font-size: 14px; color: #888; } .widget-icon { width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: white; } .tasks-icon { background-color: var(--primary); } .completed-icon { background-color: var(--secondary); } .overdue-icon { background-color: var(--accent); } .upcoming-icon { background-color: var(--warning); } .widget-value { font-size: 28px; font-weight: 600; } .widget-footer { font-size: 12px; color: #888; } .positive { color: var(--secondary); } .negative { color: var(--accent); } .panel-row { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px; } .panel { background-color: white; border-radius: 10px; box-shadow: var(--shadow); overflow: hidden; } .panel-header { padding: 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #eee; } .panel-title { font-weight: 600; display: flex; align-items: center; } .panel-icon { margin-right: 10px; color: var(--primary); } .panel-controls { display: flex; gap: 10px; } .panel-btn { background: none; border: none; color: #888; cursor: pointer; font-size: 14px; transition: var(--transition); } .panel-btn:hover { color: var(--primary); } .panel-content { padding: 20px; max-height: 300px; overflow-y: auto; } .task-list { list-style: none; } .task-item { padding: 15px; border-radius: 8px; background-color: var(--light); margin-bottom: 10px; cursor: move; transition: var(--transition); position: relative; } .task-item:hover { background-color: white; box-shadow: var(--shadow); } .task-item.dragging { opacity: 0.5; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); } .task-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .task-title { font-weight: 500; } .task-badge { padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: 600; text-transform: uppercase; } .high-priority { background-color: rgba(231, 76, 60, 0.2); color: var(--accent); } .medium-priority { background-color: rgba(243, 156, 18, 0.2); color: var(--warning); } .low-priority { background-color: rgba(46, 204, 113, 0.2); color: var(--secondary); } .task-meta { display: flex; justify-content: space-between; font-size: 12px; color: #888; } .task-progress { height: 4px; width: 100%; background-color: #eee; border-radius: 2px; margin-top: 8px; overflow: hidden; } .progress-bar { height: 100%; border-radius: 2px; transition: width 0.3s ease; } .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; } .calendar-header { display: flex; justify-content: space-between; margin-bottom: 15px; } .calendar-title { font-weight: 600; } .calendar-nav { display: flex; gap: 10px; } .calendar-nav-btn { background: none; border: none; cursor: pointer; color: #888; transition: var(--transition); } .calendar-nav-btn:hover { color: var(--primary); } .weekday { text-align: center; font-size: 12px; color: #888; padding: 5px; } .calendar-day { aspect-ratio: 1; border-radius: 5px; display: flex; flex-direction: column; justify-content: center; align-items: center; font-size: 14px; cursor: pointer; transition: var(--transition); position: relative; } .calendar-day:hover { background-color: var(--light); } .calendar-day.today { border: 2px solid var(--primary); font-weight: 600; } .calendar-day.has-events::after { content: ""; position: absolute; bottom: 5px; width: 6px; height: 6px; border-radius: 50%; background-color: var(--primary); } .calendar-day.other-month { color: #ccc; } .calendar-day.selected { background-color: var(--primary); color: white; } /* Animation styles */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse { animation: pulse 2s infinite; } @keyframes slide-in { 0% { transform: translateY(20px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } } .widget, .panel { animation: slide-in 0.3s ease forwards; } /* Make the widgets appear one after another */ .widget:nth-child(1) { animation-delay: 0.1s; } .widget:nth-child(2) { animation-delay: 0.2s; } .widget:nth-child(3) { animation-delay: 0.3s; } .widget:nth-child(4) { animation-delay: 0.4s; } /* Tooltip styles */ .tooltip { position: absolute; background-color: var(--dark); color: white; padding: 8px 12px; border-radius: 5px; font-size: 12px; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; z-index: 1000; white-space: nowrap; } .tooltip::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: var(--dark) transparent transparent transparent; } /* Responsive styles */ @media (max-width: 700px) { .dashboard { grid-template-columns: 1fr; grid-template-rows: auto auto 1fr; grid-template-areas: "header" "sidebar" "main"; } .sidebar { flex-direction: row; justify-content: space-between; padding: 10px; overflow-x: auto; } .sidebar-header { margin-bottom: 0; } .nav-menu { display: flex; margin-top: 0; margin-left: 15px; } .nav-item { margin-bottom: 0; margin-right: 10px; padding: 8px; } .panel-row { grid-template-columns: 1fr; } .search-bar { width: 200px; } } @media (max-width: 500px) { .widgets-container { grid-template-columns: 1fr; } .header { flex-direction: column; align-items: flex-start; } .search-bar { width: 100%; margin-bottom: 10px; } .nav-item span { display: none; } .nav-icon { margin-right: 0; } } /* Timer animation */ .timer-ring { width: 20px; height: 20px; border-radius: 50%; border: 2px solid #eee; display: inline-block; position: relative; margin-left: 5px; vertical-align: middle; } .timer-ring::before { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid transparent; border-top-color: var(--accent); animation: timer-spin 2s linear infinite; } @keyframes timer-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .widget-chart { height: 30px; width: 100%; display: flex; align-items: flex-end; } .chart-bar { background-color: var(--primary); opacity: 0.8; flex: 1; margin: 0 1px; border-radius: 2px 2px 0 0; transition: height 0.5s ease; } </style> </head> <body> <div class="dashboard"> <!-- Sidebar --> <div class="sidebar"> <div class="sidebar-header"> <div class="logo"></div> <div class="brand-name">ProManage</div> </div> <ul class="nav-menu"> <li class="nav-item active"> <div class="nav-icon">📊</div> <span>Dashboard</span> </li> <li class="nav-item"> <div class="nav-icon">📋</div> <span>Projects</span> </li> <li class="nav-item"> <div class="nav-icon">👥</div> <span>Team</span> </li> <li class="nav-item"> <div class="nav-icon">📈</div> <span>Reports</span> </li> <li class="nav-item"> <div class="nav-icon">⚙️</div> <span>Settings</span> </li> </ul> </div> <!-- Header --> <div class="header"> <div class="search-bar"> <div class="search-icon">🔍</div> <input type="text" placeholder="Search tasks, projects or team members..."> </div> <div class="user-profile"> <div class="avatar">AK</div> <div class="user-info"> <div class="username">Alex Kim</div> <div class="user-role">Creative Director</div> </div> </div> </div> <!-- Main Content --> <div class="main"> <h1 class="dashboard-title">Team Project Dashboard</h1> <!-- Widgets Row --> <div class="widgets-container"> <div class="widget"> <div class="widget-header"> <div class="widget-title">Active Tasks</div> <div class="widget-icon tasks-icon">📝</div> </div> <div class="widget-value">24</div> <div class="widget-footer positive"> ↑ 12% from last week </div> </div> <div class="widget"> <div class="widget-header"> <div class="widget-title">Completed</div> <div class="widget-icon completed-icon">✓</div> </div> <div class="widget-value">18</div> <div class="widget-footer positive"> ↑ 8% from last week </div> </div> <div class="widget"> <div class="widget-header"> <div class="widget-title">Overdue</div> <div class="widget-icon overdue-icon">⏰</div> </div> <div class="widget-value">5</div> <div class="widget-footer negative"> ↑ 2 more than last week </div> </div> <div class="widget"> <div class="widget-header"> <div class="widget-title">Team Efficiency</div> <div class="widget-icon upcoming-icon">⚡</div> </div> <div class="widget-chart"> <div class="chart-bar" style="height: 70%"></div> <div class="chart-bar" style="height: 85%"></div> <div class="chart-bar" style="height: 60%"></div> <div class="chart-bar" style="height: 90%"></div> <div class="chart-bar" style="height: 75%"></div> <div class="chart-bar" style="height: 80%"></div> <div class="chart-bar" style="height: 95%"></div> </div> <div class="widget-footer positive"> 87% average completion rate </div> </div> </div> <!-- Panel Row --> <div class="panel-row"> <!-- Task Panel --> <div class="panel"> <div class="panel-header"> <div class="panel-title"> <div class="panel-icon">📋</div> Current Sprint Tasks </div> <div class="panel-controls"> <button class="panel-btn" id="add-task-btn">+ Add Task</button> <button class="panel-btn">⋮</button> </div> </div> <div class="panel-content"> <ul class="task-list" id="task-list"> <li class="task-item" draggable="true" data-id="task1"> <div class="task-header"> <div class="task-title">Design homepage mockup</div> <div class="task-badge high-priority">High</div> </div> <div class="task-meta"> <div>Due in 2 days <span class="timer-ring"></span></div> <div>Assigned to: Morgan</div> </div> <div class="task-progress"> <div class="progress-bar" style="width: 75%; background-color: var(--primary);"></div> </div> </li> <li class="task-item" draggable="true" data-id="task2"> <div class="task-header"> <div class="task-title">Content strategy document</div> <div class="task-badge medium-priority">Medium</div> </div> <div class="task-meta"> <div>Due in 4 days</div> <div>Assigned to: Jamie</div> </div> <div class="task-progress"> <div class="progress-bar" style="width: 45%; background-color: var(--warning);"></div> </div> </li> <li class="task-item" draggable="true" data-id="task3"> <div class="task-header"> <div class="task-title">User research interviews</div> <div class="task-badge medium-priority">Medium</div> </div> <div class="task-meta"> <div>Due tomorrow <span class="timer-ring"></span></div> <div>Assigned to: Kai</div> </div> <div class="task-progress"> <div class="progress-bar" style="width: 30%; background-color: var(--warning);"></div> </div> </li> <li class="task-item" draggable="true" data-id="task4"> <div class="task-header"> <div class="task-title">Finalize brand guidelines</div> <div class="task-badge low-priority">Low</div> </div> <div class="task-meta"> <div>Due in 1 week</div> <div>Assigned to: Alex</div> </div> <div class="task-progress"> <div class="progress-bar" style="width: 90%; background-color: var(--secondary);"></div> </div> </li> </ul> </div> </div> <!-- Calendar Panel --> <div class="panel"> <div class="panel-header"> <div class="panel-title"> <div class="panel-icon">📅</div> Project Timeline </div> <div class="panel-controls"> <button class="panel-btn" id="today-btn">Today</button> <button class="panel-btn">⋮</button> </div> </div> <div class="panel-content"> <div class="calendar-header"> <div class="calendar-title" id="calendar-month">November 2023</div> <div class="calendar-nav"> <button class="calendar-nav-btn" id="prev-month">◀</button> <button class="calendar-nav-btn" id="next-month">▶</button> </div> </div> <div class="calendar-grid" id="calendar-grid"> <!-- Weekday headers --> <div class="weekday">Sun</div> <div class="weekday">Mon</div> <div class="weekday">Tue</div> <div class="weekday">Wed</div> <div class="weekday">Thu</div> <div class="weekday">Fri</div> <div class="weekday">Sat</div> <!-- Calendar days will be inserted here via JS --> </div> </div> </div> </div> </div> </div> <!-- Tooltip element --> <div class="tooltip" id="tooltip"></div> <script> document.addEventListener('DOMContentLoaded', function() { // Task drag and drop functionality const taskList = document.getElementById('task-list'); let draggedItem = null; taskList.addEventListener('dragstart', function(e) { if (e.target.classList.contains('task-item')) { draggedItem = e.target; setTimeout(() => { e.target.classList.add('dragging'); }, 0); } }); taskList.addEventListener('dragend', function(e) { if (e.target.classList.contains('task-item')) { e.target.classList.remove('dragging'); } }); taskList.addEventListener('dragover', function(e) { e.preventDefault(); if (draggedItem) { const afterElement = getDragAfterElement(taskList, e.clientY); const list = taskList; if (afterElement == null) { list.appendChild(draggedItem); } else { list.insertBefore(draggedItem, afterElement); } } }); function getDragAfterElement(container, y) { const draggableElements = [...container.querySelectorAll('.task-item:not(.dragging)')]; return draggableElements.reduce((closest, child) => { const box = child.getBoundingClientRect(); const offset = y - box.top - box.height / 2; if (offset < 0 && offset > closest.offset) { return { offset: offset, element: child }; } else { return closest; } }, { offset: Number.NEGATIVE_INFINITY }).element; } // Calendar functionality const calendarGrid = document.getElementById('calendar-grid'); const calendarMonth = document.getElementById('calendar-month'); const prevMonthBtn = document.getElementById('prev-month'); const nextMonthBtn = document.getElementById('next-month'); const todayBtn = document.getElementById('today-btn'); // Initialize with current month let currentDate = new Date(); let currentMonth = currentDate.getMonth(); let currentYear = currentDate.getFullYear(); // Sample events data const events = [ { date: new Date(2023, 10, 15), title: "Kickoff Meeting" }, { date: new Date(2023, 10, 18), title: "Design Review" }, { date: new Date(2023, 10, 22), title: "Sprint Planning" }, { date: new Date(2023, 10, 29), title: "Client Presentation" } ]; function renderCalendar(month, year) { // Clear previous days except weekday headers const dayElements = calendarGrid.querySelectorAll('.calendar-day'); dayElements.forEach(day => day.remove()); // Update month and year display const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; calendarMonth.textContent = `${monthNames[month]} ${year}`; // Get first day of month and total days const firstDay = new Date(year, month, 1).getDay(); // 0 = Sunday, 1 = Monday, etc. const daysInMonth = new Date(year, month + 1, 0).getDate(); // Get days from previous month to fill the calendar const daysInPrevMonth = new Date(year, month, 0).getDate(); // Create empty spaces for days from previous month for (let i = 0; i < firstDay; i++) { const prevMonthDay = daysInPrevMonth - (firstDay - 1) + i; const dayElement = createDayElement(prevMonthDay, 'calendar-day other-month'); calendarGrid.appendChild(dayElement); } // Current month days const today = new Date(); for (let i = 1; i <= daysInMonth; i++) { let className = 'calendar-day'; // Check if the day is today if (year === today.getFullYear() && month === today.getMonth() && i === today.getDate()) { className += ' today'; } // Check if the day has events const hasEvents = events.some(event => event.date.getFullYear() === year && event.date.getMonth() === month && event.date.getDate() === i ); if (hasEvents) { className += ' has-events'; } const dayElement = createDayElement(i, className); calendarGrid.appendChild(dayElement); } // Fill remaining spaces with next month days const totalDaysDisplayed = firstDay + daysInMonth; const remainingDays = 42 - totalDaysDisplayed; // 6 rows × 7 days = 42 total spaces for (let i = 1; i <= remainingDays; i++) { const dayElement = createDayElement(i, 'calendar-day other-month'); calendarGrid.appendChild(dayElement); } } function createDayElement(day, className) { const dayElement = document.createElement('div'); dayElement.className = className; dayElement.textContent = day; // Add click event to select day dayElement.addEventListener('click', function() { // Remove selected class from all days document.querySelectorAll('.calendar-day').forEach(day => { day.classList.remove('selected'); }); // Add selected class to clicked day if (!dayElement.classList.contains('other-month')) { dayElement.classList.add('selected'); } }); return dayElement; } // Initialize calendar renderCalendar(currentMonth, currentYear); // Next month button nextMonthBtn.addEventListener('click', function() { currentMonth++; if (currentMonth > 11) { currentMonth = 0; currentYear++; } renderCalendar(currentMonth, currentYear); }); // Previous month button prevMonthBtn.addEventListener('click', function() { currentMonth--; if (currentMonth < 0) { currentMonth = 11; currentYear--; } renderCalendar(currentMonth, currentYear); }); // Today button todayBtn.addEventListener('click', function() { const nowDate = new Date(); currentMonth = nowDate.getMonth(); currentYear = nowDate.getFullYear(); renderCalendar(currentMonth, currentYear); }); // Add Task Button const addTaskBtn = document.getElementById('add-task-btn'); addTaskBtn.addEventListener('click', function() { const newTask = document.createElement('li'); newTask.className = 'task-item'; newTask.draggable = true; newTask.dataset.id = `task${Date.now()}`; newTask.innerHTML = ` <div class="task-header"> <div class="task-title">New task</div> <div class="task-badge medium-priority">Medium</div> </div> <div class="task-meta"> <div>Not scheduled yet</div> <div>Unassigned</div> </div> <div class="task-progress"> <div class="progress-bar" style="width: 0%; background-color: var(--warning);"></div> </div> `; // Add to task list with animation newTask.style.opacity = '0'; newTask.style.transform = 'translateY(20px)'; taskList.prepend(newTask); // Trigger reflow void newTask.offsetWidth; // Apply transition newTask.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; newTask.style.opacity = '1'; newTask.style.transform = 'translateY(0)'; }); // Tooltip functionality const tooltip = document.getElementById('tooltip'); function showTooltip(element, text) { const rect = element.getBoundingClientRect(); tooltip.textContent = text; tooltip.style.top = `${rect.top - 40}px`; tooltip.style.left = `${rect.left + (rect.width / 2) - (tooltip.offsetWidth / 2)}px`; tooltip.style.opacity = '1'; } function hideTooltip() { tooltip.style.opacity = '0'; } // Add tooltips to tasks document.querySelectorAll('.task-badge').forEach(badge => { badge.addEventListener('mouseenter', function() { let tooltipText = 'Normal priority'; if (badge.classList.contains('high-priority')) { tooltipText = 'Critical - Complete ASAP'; } else if (badge.classList.contains('medium-priority')) { tooltipText = 'Important - Schedule time'; } else if (badge.classList.contains('low-priority')) { tooltipText = 'Low urgency - When time permits'; } showTooltip(badge, tooltipText); }); badge.addEventListener('mouseleave', hideTooltip); }); // Add tooltips to calendar events document.querySelectorAll('.calendar-day.has-events').forEach(day => { day.addEventListener('mouseenter', function() { const dayNum = parseInt(day.textContent); const matchingEvents = events.filter(event => event.date.getFullYear() === currentYear && event.date.getMonth() === currentMonth && event.date.getDate() === dayNum ); if (matchingEvents.length > 0) { const tooltipText = matchingEvents.map(event => event.title).join(', '); showTooltip(day, tooltipText); } }); day.addEventListener('mouseleave', hideTooltip); }); // Randomly animate chart bars setInterval(() => { document.querySelectorAll('.chart-bar').forEach(bar => { const randomHeight = 50 + Math.floor(Math.random() * 50); bar.style.height = `${randomHeight}%`; }); }, 3000); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Social Media Engagement Dashboard</title> <style> @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); :root { --primary-gradient: linear-gradient(135deg, #6e48aa 0%, #9d50bb 100%); --secondary-gradient: linear-gradient(135deg, #42e695 0%, #3bb2b8 100%); --accent-gradient: linear-gradient(135deg, #f6d365 0%, #fda085 100%); --danger-gradient: linear-gradient(135deg, #ff6b6b 0%, #ff8e8e 100%); --success-gradient: linear-gradient(135deg, #0ba360 0%, #3cba92 100%); --card-bg: rgba(255, 255, 255, 0.9); --card-shadow: 0 10px 20px rgba(0, 0, 0, 0.08); --text-primary: #2d3748; --text-secondary: #4a5568; --text-muted: #718096; --border-color: rgba(226, 232, 240, 0.8); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body { background-color: #f7fafc; color: var(--text-primary); overflow-x: hidden; height: 100vh; width: 100%; display: flex; flex-direction: column; } .dashboard-container { max-width: 700px; width: 100%; height: 700px; margin: 0 auto; padding: 20px; display: flex; flex-direction: column; overflow: hidden; position: relative; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .brand { display: flex; align-items: center; gap: 10px; } .brand-icon { width: 36px; height: 36px; border-radius: 10px; background: var(--primary-gradient); display: grid; place-items: center; color: white; font-size: 20px; box-shadow: 0 4px 10px rgba(110, 72, 170, 0.3); } .brand-name { font-weight: 600; font-size: 20px; } .time-filter { display: flex; gap: 8px; background: white; border-radius: 20px; padding: 5px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } .time-option { padding: 5px 12px; border-radius: 15px; font-size: 13px; cursor: pointer; transition: all 0.3s ease; } .time-option.active { background: var(--primary-gradient); color: white; box-shadow: 0 4px 10px rgba(110, 72, 170, 0.3); } .dashboard-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 20px; } .stat-card { background: var(--card-bg); border-radius: 15px; padding: 15px; box-shadow: var(--card-shadow); display: flex; flex-direction: column; transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; overflow: hidden; } .stat-card:hover { transform: translateY(-5px); box-shadow: 0 12px 25px rgba(0, 0, 0, 0.12); } .stat-card::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; } .stat-card.likes::after { background: var(--primary-gradient); } .stat-card.comments::after { background: var(--secondary-gradient); } .stat-card.shares::after { background: var(--accent-gradient); } .stat-title { font-size: 14px; color: var(--text-secondary); margin-bottom: 5px; display: flex; align-items: center; gap: 6px; } .stat-value { font-size: 24px; font-weight: 600; margin-bottom: 5px; } .stat-change { font-size: 12px; padding: 3px 8px; border-radius: 10px; display: inline-flex; align-items: center; gap: 4px; font-weight: 500; } .increase { background-color: rgba(12, 163, 96, 0.1); color: #0ca360; } .decrease { background-color: rgba(255, 107, 107, 0.1); color: #ff6b6b; } .engagement-chart-container { background: var(--card-bg); border-radius: 15px; padding: 20px; box-shadow: var(--card-shadow); margin-bottom: 20px; height: 250px; position: relative; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .chart-title { font-size: 16px; font-weight: 600; } .platform-filter { display: flex; gap: 10px; } .platform-option { display: flex; align-items: center; gap: 6px; font-size: 13px; padding: 5px 10px; border-radius: 20px; cursor: pointer; transition: all 0.2s ease; } .platform-option:hover { background-color: rgba(226, 232, 240, 0.5); } .platform-option.active { background-color: rgba(110, 72, 170, 0.1); color: #6e48aa; font-weight: 500; } .platform-icon { width: 18px; height: 18px; display: grid; place-items: center; font-size: 11px; } .chart-canvas { width: 100%; height: 180px; } .recent-posts { background: var(--card-bg); border-radius: 15px; padding: 20px; box-shadow: var(--card-shadow); flex: 1; overflow: hidden; display: flex; flex-direction: column; } .post-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .post-title { font-size: 16px; font-weight: 600; } .view-all { font-size: 13px; color: #6e48aa; display: flex; align-items: center; gap: 5px; cursor: pointer; transition: color 0.2s ease; } .view-all:hover { color: #9d50bb; } .post-list { overflow-y: auto; flex: 1; padding-right: 5px; } .post-list::-webkit-scrollbar { width: 5px; } .post-list::-webkit-scrollbar-track { background: rgba(226, 232, 240, 0.5); border-radius: 10px; } .post-list::-webkit-scrollbar-thumb { background: rgba(110, 72, 170, 0.3); border-radius: 10px; } .post-list::-webkit-scrollbar-thumb:hover { background: rgba(110, 72, 170, 0.5); } .post-item { display: flex; gap: 15px; padding: 12px; border-radius: 10px; transition: background-color 0.2s ease; margin-bottom: 10px; cursor: pointer; position: relative; } .post-item:hover { background-color: rgba(226, 232, 240, 0.5); } .post-item.hot::before { content: '🔥'; position: absolute; top: -8px; right: -8px; font-size: 16px; filter: drop-shadow(0 0 2px white); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .post-thumb { width: 50px; height: 50px; border-radius: 10px; overflow: hidden; flex-shrink: 0; } .post-thumb img { width: 100%; height: 100%; object-fit: cover; } .post-details { flex: 1; display: flex; flex-direction: column; gap: 5px; } .post-content { font-size: 13px; line-height: 1.4; color: var(--text-secondary); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .post-meta { display: flex; align-items: center; justify-content: space-between; } .post-time { font-size: 11px; color: var(--text-muted); } .post-stats { display: flex; gap: 8px; } .post-stat { display: flex; align-items: center; gap: 3px; font-size: 11px; color: var(--text-muted); } .post-platform { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--text-muted); padding: 2px 6px; border-radius: 10px; background-color: rgba(226, 232, 240, 0.5); } .post-platform.instagram { background-color: rgba(225, 48, 108, 0.1); color: #e1306c; } .post-platform.twitter { background-color: rgba(29, 161, 242, 0.1); color: #1da1f2; } .post-platform.facebook { background-color: rgba(24, 119, 242, 0.1); color: #1877f2; } .post-platform.linkedin { background-color: rgba(0, 119, 181, 0.1); color: #0077b5; } .heatmap-tooltip { position: absolute; background: white; border-radius: 8px; padding: 10px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); font-size: 12px; pointer-events: none; transition: opacity 0.2s ease; z-index: 100; max-width: 200px; opacity: 0; } .tooltip-title { font-weight: 600; margin-bottom: 5px; } .tooltip-content { display: flex; flex-direction: column; gap: 5px; } .tooltip-stat { display: flex; justify-content: space-between; } .tooltip-platform { display: inline-block; padding: 2px 6px; border-radius: 10px; font-size: 10px; margin-top: 5px; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .dashboard-container { animation: fadeIn 0.5s ease forwards; } .stat-card { animation: fadeIn 0.5s ease forwards; animation-delay: calc(var(--i) * 0.1s); opacity: 0; } /* Responsive adjustments */ @media (max-width: 600px) { .dashboard-stats { grid-template-columns: repeat(2, 1fr); } .platform-filter { flex-wrap: wrap; } } @media (max-width: 500px) { .dashboard-stats { grid-template-columns: 1fr; } .time-filter { display: none; } } /* Interactive hover effects */ .interactive-point { position: absolute; width: 10px; height: 10px; background: rgba(110, 72, 170, 0.7); border-radius: 50%; transform: translate(-50%, -50%); cursor: pointer; transition: all 0.2s ease; z-index: 2; } .interactive-point:hover { transform: translate(-50%, -50%) scale(1.5); background: rgba(110, 72, 170, 1); } .interactive-point::after { content: ''; position: absolute; width: 20px; height: 20px; border-radius: 50%; border: 2px solid rgba(110, 72, 170, 0.3); top: -7px; left: -7px; animation: ripple 1.5s infinite; } @keyframes ripple { 0% { transform: scale(0.8); opacity: 1; } 100% { transform: scale(1.5); opacity: 0; } } .notification-badge { position: absolute; top: -5px; right: -5px; background: var(--danger-gradient); color: white; border-radius: 50%; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; box-shadow: 0 2px 5px rgba(255, 107, 107, 0.4); } </style> </head> <body> <div class="dashboard-container"> <div class="dashboard-header"> <div class="brand"> <div class="brand-icon"> <i>📊</i> </div> <div class="brand-name">SocialPulse</div> </div> <div class="time-filter"> <div class="time-option" data-value="day">Day</div> <div class="time-option active" data-value="week">Week</div> <div class="time-option" data-value="month">Month</div> <div class="time-option" data-value="quarter">Quarter</div> </div> </div> <div class="dashboard-stats"> <div class="stat-card likes" style="--i: 1"> <div class="stat-title"> <i>👍</i> Total Likes </div> <div class="stat-value">24,835</div> <div class="stat-change increase"> <i>↑</i> 13.2% vs last week </div> </div> <div class="stat-card comments" style="--i: 2"> <div class="stat-title"> <i>💬</i> Comments </div> <div class="stat-value">3,427</div> <div class="stat-change increase"> <i>↑</i> 8.7% vs last week </div> </div> <div class="stat-card shares" style="--i: 3"> <div class="stat-title"> <i>🔄</i> Shares </div> <div class="stat-value">5,163</div> <div class="stat-change decrease"> <i>↓</i> 2.5% vs last week </div> </div> </div> <div class="engagement-chart-container"> <div class="chart-header"> <div class="chart-title">Engagement Heatmap</div> <div class="platform-filter"> <div class="platform-option active" data-platform="all"> <div class="platform-icon">📱</div> All </div> <div class="platform-option" data-platform="instagram"> <div class="platform-icon">📸</div> Instagram </div> <div class="platform-option" data-platform="twitter"> <div class="platform-icon">🐦</div> Twitter </div> <div class="platform-option" data-platform="facebook"> <div class="platform-icon">👥</div> Facebook </div> </div> </div> <canvas id="engagementChart" class="chart-canvas"></canvas> <!-- Interactive points will be added via JS --> <div class="heatmap-tooltip" id="heatmapTooltip"></div> </div> <div class="recent-posts"> <div class="post-header"> <div class="post-title">Top Performing Posts</div> <div class="view-all">View all <i>→</i></div> </div> <div class="post-list"> <div class="post-item hot"> <div class="post-thumb"> <img src="https://source.unsplash.com/random/100x100?summer" alt="Post thumbnail"> </div> <div class="post-details"> <div class="post-content">"Summer vibes! Our new eco-friendly collection is finally here. Tag a friend who needs this in their life! #SummerEssentials"</div> <div class="post-meta"> <div class="post-platform instagram"> <i>📸</i> Instagram </div> <div class="post-stats"> <div class="post-stat"> <i>👍</i> 4.2K </div> <div class="post-stat"> <i>💬</i> 328 </div> <div class="post-time">2h ago</div> </div> </div> </div> </div> <div class="post-item"> <div class="post-thumb"> <img src="https://source.unsplash.com/random/100x100?tech" alt="Post thumbnail"> </div> <div class="post-details"> <div class="post-content">"Breaking: We've just partnered with @TechGiants to bring you exclusive access to their AI tools. Learn how this can transform your workflow!"</div> <div class="post-meta"> <div class="post-platform twitter"> <i>🐦</i> Twitter </div> <div class="post-stats"> <div class="post-stat"> <i>👍</i> 2.8K </div> <div class="post-stat"> <i>🔄</i> 1.5K </div> <div class="post-time">6h ago</div> </div> </div> </div> </div> <div class="post-item"> <div class="post-thumb"> <img src="https://source.unsplash.com/random/100x100?people" alt="Post thumbnail"> </div> <div class="post-details"> <div class="post-content">"Meet Sarah, our Customer Success Manager who helped @BigBrand increase their engagement by 267% in just 3 months. Swipe to see how she did it!"</div> <div class="post-meta"> <div class="post-platform linkedin"> <i>💼</i> LinkedIn </div> <div class="post-stats"> <div class="post-stat"> <i>👍</i> 1.2K </div> <div class="post-stat"> <i>💬</i> 86 </div> <div class="post-time">1d ago</div> </div> </div> </div> </div> <div class="post-item"> <div class="post-thumb"> <img src="https://source.unsplash.com/random/100x100?event" alt="Post thumbnail"> </div> <div class="post-details"> <div class="post-content">"🚨 Last chance to register! Our Digital Marketing Masterclass starts in 48 hours. Limited spots available - secure yours now!"</div> <div class="post-meta"> <div class="post-platform facebook"> <i>👥</i> Facebook </div> <div class="post-stats"> <div class="post-stat"> <i>👍</i> 983 </div> <div class="post-stat"> <i>🔄</i> 325 </div> <div class="post-time">1d ago</div> </div> </div> </div> </div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Time filter functionality const timeOptions = document.querySelectorAll('.time-option'); timeOptions.forEach(option => { option.addEventListener('click', function() { timeOptions.forEach(opt => opt.classList.remove('active')); this.classList.add('active'); updateDashboardData(this.getAttribute('data-value')); }); }); // Platform filter functionality const platformOptions = document.querySelectorAll('.platform-option'); platformOptions.forEach(option => { option.addEventListener('click', function() { platformOptions.forEach(opt => opt.classList.remove('active')); this.classList.add('active'); updateChartData(this.getAttribute('data-platform')); }); }); // Initialize heatmap chart const ctx = document.getElementById('engagementChart').getContext('2d'); const gradientFill = ctx.createLinearGradient(0, 0, 0, 200); gradientFill.addColorStop(0, 'rgba(110, 72, 170, 0.8)'); gradientFill.addColorStop(1, 'rgba(110, 72, 170, 0.1)'); const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; const engagementChart = new Chart(ctx, { type: 'line', data: { labels: days, datasets: [{ label: 'Total Engagement', data: [5230, 6800, 8200, 7500, 9300, 11200, 10500], backgroundColor: gradientFill, borderColor: 'rgba(110, 72, 170, 1)', borderWidth: 3, pointBackgroundColor: 'white', pointBorderColor: 'rgba(110, 72, 170, 1)', pointBorderWidth: 2, pointRadius: 5, pointHoverRadius: 7, tension: 0.3, fill: true }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { enabled: false } }, scales: { y: { beginAtZero: true, grid: { color: 'rgba(226, 232, 240, 0.5)', drawBorder: false }, ticks: { font: { size: 10, family: 'Poppins' }, color: '#718096', callback: function(value) { if (value >= 1000) { return value / 1000 + 'k'; } return value; } } }, x: { grid: { display: false }, ticks: { font: { size: 10, family: 'Poppins' }, color: '#718096' } } }, interaction: { intersect: false, mode: 'index' } } }); // Add interactive points to the chart const chartContainer = document.querySelector('.engagement-chart-container'); const tooltip = document.getElementById('heatmapTooltip'); // Sample data for interactive points const interactivePoints = [ { x: 25, y: 55, title: 'Campaign Launch', platform: 'instagram', stats: { likes: '3.2K', comments: '245', shares: '1.1K' } }, { x: 52, y: 38, title: 'Product Announcement', platform: 'twitter', stats: { likes: '2.8K', comments: '532', shares: '1.9K' } }, { x: 75, y: 20, title: 'Flash Sale', platform: 'facebook', stats: { likes: '4.5K', comments: '173', shares: '897' } } ]; // Create and position interactive points interactivePoints.forEach(point => { const interactivePoint = document.createElement('div'); interactivePoint.className = 'interactive-point'; interactivePoint.style.left = `${point.x}%`; interactivePoint.style.top = `${point.y}%`; // Add notification badge to some points if (Math.random() > 0.5) { const badge = document.createElement('div'); badge.className = 'notification-badge'; badge.textContent = '!'; interactivePoint.appendChild(badge); } chartContainer.appendChild(interactivePoint); // Show tooltip on hover interactivePoint.addEventListener('mouseenter', function(e) { tooltip.innerHTML = ` <div class="tooltip-title">${point.title}</div> <div class="tooltip-content"> <div class="tooltip-stat"><span>Likes:</span> <span>${point.stats.likes}</span></div> <div class="tooltip-stat"><span>Comments:</span> <span>${point.stats.comments}</span></div> <div class="tooltip-stat"><span>Shares:</span> <span>${point.stats.shares}</span></div> <div class="tooltip-platform ${point.platform}">${point.platform.charAt(0).toUpperCase() + point.platform.slice(1)}</div> </div> `; // Calculate tooltip position const pointRect = interactivePoint.getBoundingClientRect(); const containerRect = chartContainer.getBoundingClientRect(); tooltip.style.left = `${pointRect.left - containerRect.left + 15}px`; tooltip.style.top = `${pointRect.top - containerRect.top - 15}px`; tooltip.style.opacity = '1'; }); interactivePoint.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; }); }); // Function to update dashboard data based on time filter function updateDashboardData(timeframe) { // Simulate data updates const timeframeMultipliers = { day: 0.15, week: 1, month: 4.2, quarter: 12.5 }; const multiplier = timeframeMultipliers[timeframe]; // Update stat cards with animation document.querySelector('.stat-card.likes .stat-value').textContent = numberWithCommas(Math.round(24835 * multiplier)); document.querySelector('.stat-card.comments .stat-value').textContent = numberWithCommas(Math.round(3427 * multiplier)); document.querySelector('.stat-card.shares .stat-value').textContent = numberWithCommas(Math.round(5163 * multiplier)); // Update chart data const baseData = [5230, 6800, 8200, 7500, 9300, 11200, 10500]; engagementChart.data.datasets[0].data = baseData.map(val => Math.round(val * multiplier)); engagementChart.update(); } // Function to update chart data based on platform filter function updateChartData(platform) { // Simulate different data for each platform const platformData = { all: [5230, 6800, 8200, 7500, 9300, 11200, 10500], instagram: [3200, 4100, 5300, 4800, 6200, 7500, 6900], twitter: [1200, 1800, 1500, 1300, 1900, 2200, 2000], facebook: [830, 900, 1400, 1400, 1200, 1500, 1600] }; // Platform-specific colors const platformColors = { all: { border: 'rgba(110, 72, 170, 1)', background: 'rgba(110, 72, 170, 0.8)' }, instagram: { border: 'rgba(225, 48, 108, 1)', background: 'rgba(225, 48, 108, 0.8)' }, twitter: { border: 'rgba(29, 161, 242, 1)', background: 'rgba(29, 161, 242, 0.8)' }, facebook: { border: 'rgba(24, 119, 242, 1)', background: 'rgba(24, 119, 242, 0.8)' } }; // Update chart with platform data engagementChart.data.datasets[0].data = platformData[platform]; // Update chart colors const gradientFill = ctx.createLinearGradient(0, 0, 0, 200); gradientFill.addColorStop(0, platformColors[platform].background); gradientFill.addColorStop(1, platformColors[platform].background.replace('0.8', '0.1')); engagementChart.data.datasets[0].backgroundColor = gradientFill; engagementChart.data.datasets[0].borderColor = platformColors[platform].border; engagementChart.data.datasets[0].pointBorderColor = platformColors[platform].border; engagementChart.update(); } // Helper function to format numbers with commas function numberWithCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } // Post item hover effects const postItems = document.querySelectorAll('.post-item'); postItems.forEach(item => { item.addEventListener('mouseenter', function() { postItems.forEach(otherItem => { if (otherItem !== item) { otherItem.style.opacity = '0.7'; } }); }); item.addEventListener('mouseleave', function() { postItems.forEach(otherItem => { otherItem.style.opacity = '1'; }); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Smart City Operations Dashboard</title> <style> :root { --primary: #0B132B; --secondary: #1C2541; --tertiary: #3A506B; --accent: #00FFCC; --accent-alt: #5BC0BE; --danger: #FF3864; --warning: #FFCC00; --success: #00E676; --text: #E0E1DD; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--primary); color: var(--text); overflow-x: hidden; height: 700px; width: 700px; max-width: 100%; } .dashboard { display: grid; grid-template-rows: auto 1fr auto; height: 100%; max-height: 700px; overflow: hidden; } header { background-color: var(--secondary); padding: 12px 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(255, 255, 255, 0.1); position: relative; z-index: 10; } .logo { display: flex; align-items: center; gap: 10px; } .logo-icon { width: 30px; height: 30px; background: linear-gradient(135deg, var(--accent), var(--accent-alt)); border-radius: 8px; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 15px rgba(0, 255, 204, 0.4); } .logo-text { font-weight: 700; font-size: 18px; background: linear-gradient(to right, var(--accent), var(--accent-alt)); -webkit-background-clip: text; background-clip: text; color: transparent; } .controls { display: flex; gap: 15px; } .control-btn { background-color: var(--tertiary); border: none; color: var(--text); width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; position: relative; } .control-btn:hover { background-color: rgba(58, 80, 107, 0.8); transform: translateY(-2px); } .control-btn.active { background-color: var(--accent); color: var(--primary); } .control-btn.active:before { content: ''; position: absolute; width: 100%; height: 100%; border-radius: 8px; box-shadow: 0 0 15px var(--accent); animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(0, 255, 204, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(0, 255, 204, 0); } 100% { box-shadow: 0 0 0 0 rgba(0, 255, 204, 0); } } main { display: grid; grid-template-columns: 3fr 1fr; gap: 15px; padding: 15px; max-height: calc(100% - 120px); overflow: hidden; } .map-container { background-color: var(--secondary); border-radius: 12px; overflow: hidden; position: relative; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); } .map { width: 100%; height: 100%; background: radial-gradient(circle at center, var(--tertiary) 0%, var(--secondary) 100%); position: relative; overflow: hidden; } .map:before { content: ''; position: absolute; width: 100%; height: 100%; top: 0; left: 0; background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%233A506B' fill-opacity='0.2'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); } .grid-lines { position: absolute; width: 100%; height: 100%; background-size: 50px 50px; background-image: linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px), linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px); } .city-markers { position: absolute; width: 100%; height: 100%; } .marker { position: absolute; transform: translate(-50%, -50%); cursor: pointer; transition: all 0.3s ease; } .marker .pulse { width: 12px; height: 12px; border-radius: 50%; animation: markerPulse 3s infinite; box-shadow: 0 0 10px currentColor; } .marker:hover { transform: translate(-50%, -50%) scale(1.3); } .marker.traffic { color: var(--warning); } .marker.energy { color: var(--accent); } .marker.safety { color: var(--danger); } .marker.environmental { color: var(--success); } @keyframes markerPulse { 0% { transform: scale(0.6); opacity: 1; } 50% { opacity: 0.5; } 100% { transform: scale(1); opacity: 1; } } .info-box { position: absolute; background-color: rgba(28, 37, 65, 0.95); border: 1px solid var(--accent); border-radius: 8px; padding: 15px; width: 250px; box-shadow: 0 0 20px rgba(0, 255, 204, 0.2); opacity: 0; transform: translateY(10px); transition: all 0.3s ease; z-index: 100; pointer-events: none; } .info-box.active { opacity: 1; transform: translateY(0); } .info-box h4 { margin-bottom: 10px; color: var(--accent); display: flex; align-items: center; gap: 8px; } .info-box p { font-size: 14px; margin-bottom: 8px; } .info-box .metric { display: flex; justify-content: space-between; align-items: center; margin-top: 5px; } .info-box .metric span { font-weight: bold; } .map-controls { position: absolute; right: 15px; top: 15px; display: flex; flex-direction: column; gap: 10px; } .map-control-btn { background-color: rgba(11, 19, 43, 0.9); color: var(--text); width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; border: 1px solid rgba(255, 255, 255, 0.1); cursor: pointer; transition: all 0.2s ease; } .map-control-btn:hover { background-color: var(--tertiary); border-color: var(--accent); } .map-layers { position: absolute; left: 15px; top: 15px; background-color: rgba(11, 19, 43, 0.9); border-radius: 8px; padding: 10px; border: 1px solid rgba(255, 255, 255, 0.1); } .layer-option { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; cursor: pointer; } .layer-option:last-child { margin-bottom: 0; } .layer-color { width: 12px; height: 12px; border-radius: 3px; } .layer-color.traffic { background-color: var(--warning); } .layer-color.energy { background-color: var(--accent); } .layer-color.safety { background-color: var(--danger); } .layer-color.environmental { background-color: var(--success); } .layer-name { font-size: 13px; } .sidebar { display: flex; flex-direction: column; gap: 15px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--accent) var(--secondary); } .sidebar::-webkit-scrollbar { width: 5px; } .sidebar::-webkit-scrollbar-track { background: var(--secondary); } .sidebar::-webkit-scrollbar-thumb { background-color: var(--tertiary); border-radius: 6px; } .data-card { background-color: var(--secondary); border-radius: 12px; padding: 15px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); } .data-card h3 { font-size: 16px; margin-bottom: 12px; color: var(--accent); display: flex; align-items: center; gap: 8px; } .data-point { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 14px; } .data-value { font-weight: 600; } .data-chart { height: 100px; width: 100%; margin-top: 10px; position: relative; overflow: hidden; } .chart-bar { position: absolute; bottom: 0; width: 8px; background: linear-gradient(to top, var(--accent), rgba(0, 255, 204, 0.2)); border-radius: 3px 3px 0 0; transition: height 0.5s ease; } .alerts { max-height: 170px; overflow-y: auto; } .alert-item { padding: 10px; border-radius: 8px; margin-bottom: 8px; font-size: 13px; border-left: 3px solid; background-color: rgba(28, 37, 65, 0.5); display: flex; align-items: center; gap: 10px; } .alert-item:last-child { margin-bottom: 0; } .alert-item.high { border-color: var(--danger); } .alert-item.medium { border-color: var(--warning); } .alert-item.low { border-color: var(--success); } .alert-icon { min-width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; border-radius: 50%; color: var(--primary); font-weight: bold; font-size: 10px; } .alert-item.high .alert-icon { background-color: var(--danger); } .alert-item.medium .alert-icon { background-color: var(--warning); } .alert-item.low .alert-icon { background-color: var(--success); } .alert-content { flex: 1; } .alert-time { color: rgba(224, 225, 221, 0.6); font-size: 11px; margin-top: 3px; } footer { background-color: var(--secondary); padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; font-size: 14px; border-top: 1px solid rgba(255, 255, 255, 0.1); } .footer-status { display: flex; align-items: center; gap: 5px; } .status-indicator { width: 8px; height: 8px; border-radius: 50%; background-color: var(--success); box-shadow: 0 0 10px var(--success); } .footer-actions { display: flex; gap: 15px; } .footer-action { color: var(--text); opacity: 0.8; cursor: pointer; transition: all 0.2s ease; } .footer-action:hover { opacity: 1; color: var(--accent); } @media (max-width: 700px) { main { grid-template-columns: 1fr; grid-template-rows: 1fr auto; overflow-y: auto; } .map-container { height: 300px; } } /* Animation for the dashboard load */ .loading { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: var(--primary); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 1000; transition: opacity 0.5s ease, visibility 0.5s ease; } .loading.hidden { opacity: 0; visibility: hidden; } .loading-icon { width: 60px; height: 60px; border-radius: 30px; border: 3px solid var(--tertiary); border-top: 3px solid var(--accent); animation: spin 1s linear infinite; margin-bottom: 20px; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading-text { color: var(--accent); font-size: 18px; margin-top: 10px; } .loading-progress { width: 200px; height: 4px; background-color: var(--tertiary); border-radius: 2px; overflow: hidden; margin-top: 10px; } .loading-progress-bar { height: 100%; width: 0%; background-color: var(--accent); transition: width 0.3s ease; } /* Custom animations */ .data-pulse { position: absolute; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none; z-index: 0; } .pulse-dot { position: absolute; width: 2px; height: 2px; border-radius: 50%; background-color: var(--accent); opacity: 0; animation: dataPulse 2s ease-out; } @keyframes dataPulse { 0% { transform: scale(1); opacity: 0.8; } 100% { transform: scale(20); opacity: 0; } } .grid-line { position: absolute; background-color: rgba(0, 255, 204, 0.1); } .grid-line-h { height: 1px; width: 100%; animation: scan-h 8s linear infinite; } .grid-line-v { width: 1px; height: 100%; animation: scan-v 12s linear infinite; } @keyframes scan-h { 0% { top: 0; opacity: 0; } 5% { opacity: 1; } 50% { opacity: 0.5; } 95% { opacity: 1; } 100% { top: 100%; opacity: 0; } } @keyframes scan-v { 0% { left: 0; opacity: 0; } 5% { opacity: 1; } 50% { opacity: 0.5; } 95% { opacity: 1; } 100% { left: 100%; opacity: 0; } } .notification { position: fixed; top: 20px; right: -300px; width: 250px; background-color: var(--secondary); border-left: 4px solid var(--accent); padding: 15px; border-radius: 8px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); z-index: 1000; transition: right 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .notification.show { right: 20px; } .notification h4 { margin-bottom: 8px; color: var(--accent); } .notification p { font-size: 13px; margin-bottom: 0; } </style> </head> <body> <div class="loading"> <div class="loading-icon"></div> <div class="loading-text">Initializing Smart City Dashboard</div> <div class="loading-progress"> <div class="loading-progress-bar"></div> </div> </div> <div class="dashboard"> <header> <div class="logo"> <div class="logo-icon"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="#0B132B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 17L12 22L22 17" stroke="#0B132B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 12L12 17L22 12" stroke="#0B132B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <span class="logo-text">MetroPulse</span> </div> <div class="controls"> <button class="control-btn active" id="realTimeBtn" title="Real-time mode"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" /> <path d="M12 6V12L16 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> </svg> </button> <button class="control-btn" id="analyticsBtn" title="Analytics mode"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M18 20V10" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> <path d="M12 20V4" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> <path d="M6 20V14" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> </svg> </button> <button class="control-btn" id="alertsBtn" title="Alerts"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L1 21H23L12 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M12 16V16.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M12 10V14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </button> <button class="control-btn" id="settingsBtn" title="Settings"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M19.4 15C19.2669 15.3016 19.2272 15.6362 19.286 15.9606C19.3448 16.285 19.4995 16.5843 19.73 16.82L19.79 16.88C19.976 17.0657 20.1235 17.2863 20.2241 17.5291C20.3248 17.7719 20.3766 18.0322 20.3766 18.295C20.3766 18.5578 20.3248 18.8181 20.2241 19.0609C20.1235 19.3037 19.976 19.5243 19.79 19.71C19.6043 19.896 19.3837 20.0435 19.1409 20.1441C18.8981 20.2448 18.6378 20.2966 18.375 20.2966C18.1122 20.2966 17.8519 20.2448 17.6091 20.1441C17.3663 20.0435 17.1457 19.896 16.96 19.71L16.9 19.65C16.6643 19.4195 16.365 19.2648 16.0406 19.206C15.7162 19.1472 15.3816 19.1869 15.08 19.32C14.7842 19.4468 14.532 19.6572 14.3543 19.9255C14.1766 20.1938 14.0813 20.5082 14.08 20.83V21C14.08 21.5304 13.8693 22.0391 13.4942 22.4142C13.1191 22.7893 12.6104 23 12.08 23C11.5496 23 11.0409 22.7893 10.6658 22.4142C10.2907 22.0391 10.08 21.5304 10.08 21V20.91C10.0723 20.579 9.96512 20.258 9.77251 19.9887C9.5799 19.7194 9.31074 19.5143 9 19.4C8.69838 19.2669 8.36381 19.2272 8.03941 19.286C7.71502 19.3448 7.41568 19.4995 7.18 19.73L7.12 19.79C6.93425 19.976 6.71368 20.1235 6.47088 20.2241C6.22808 20.3248 5.96783 20.3766 5.705 20.3766C5.44217 20.3766 5.18192 20.3248 4.93912 20.2241C4.69632 20.1235 4.47575 19.976 4.29 19.79C4.10405 19.6043 3.95653 19.3837 3.85588 19.1409C3.75523 18.8981 3.70343 18.6378 3.70343 18.375C3.70343 18.1122 3.75523 17.8519 3.85588 17.6091C3.95653 17.3663 4.10405 17.1457 4.29 16.96L4.35 16.9C4.58054 16.6643 4.73519 16.365 4.794 16.0406C4.85282 15.7162 4.81312 15.3816 4.68 15.08C4.55324 14.7842 4.34276 14.532 4.07447 14.3543C3.80618 14.1766 3.49179 14.0813 3.17 14.08H3C2.46957 14.08 1.96086 13.8693 1.58579 13.4942C1.21071 13.1191 1 12.6104 1 12.08C1 11.5496 1.21071 11.0409 1.58579 10.6658C1.96086 10.2907 2.46957 10.08 3 10.08H3.09C3.42099 10.0723 3.742 9.96512 4.0113 9.77251C4.28059 9.5799 4.48572 9.31074 4.6 9C4.73312 8.69838 4.77282 8.36381 4.714 8.03941C4.65519 7.71502 4.50054 7.41568 4.27 7.18L4.21 7.12C4.02405 6.93425 3.87653 6.71368 3.77588 6.47088C3.67523 6.22808 3.62343 5.96783 3.62343 5.705C3.62343 5.44217 3.67523 5.18192 3.77588 4.93912C3.87653 4.69632 4.02405 4.47575 4.21 4.29C4.39575 4.10405 4.61632 3.95653 4.85912 3.85588C5.10192 3.75523 5.36217 3.70343 5.625 3.70343C5.88783 3.70343 6.14808 3.75523 6.39088 3.85588C6.63368 3.95653 6.85425 4.10405 7.04 4.29L7.1 4.35C7.33568 4.58054 7.63502 4.73519 7.95941 4.794C8.28381 4.85282 8.61838 4.81312 8.92 4.68H9C9.29577 4.55324 9.54802 4.34276 9.72569 4.07447C9.90337 3.80618 9.99872 3.49179 10 3.17V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0013 3.41179 14.0966 3.72618 14.2743 3.99447C14.452 4.26276 14.7042 4.47324 15 4.6C15.3016 4.73312 15.6362 4.77282 15.9606 4.714C16.285 4.65519 16.5843 4.50054 16.82 4.27L16.88 4.21C17.0657 4.02405 17.2863 3.87653 17.5291 3.77588C17.7719 3.67523 18.0322 3.62343 18.295 3.62343C18.5578 3.62343 18.8181 3.67523 19.0609 3.77588C19.3037 3.87653 19.5243 4.02405 19.71 4.21C19.896 4.39575 20.0435 4.61632 20.1441 4.85912C20.2448 5.10192 20.2966 5.36217 20.2966 5.625C20.2966 5.88783 20.2448 6.14808 20.1441 6.39088C20.0435 6.63368 19.896 6.85425 19.71 7.04L19.65 7.1C19.4195 7.33568 19.2648 7.63502 19.206 7.95941C19.1472 8.28381 19.1869 8.61838 19.32 8.92V9C19.4468 9.29577 19.6572 9.54802 19.9255 9.72569C20.1938 9.90337 20.5082 9.99872 20.83 10H21C21.5304 10 22.0391 10.2107 22.4142 10.5858C22.7893 10.9609 23 11.4696 23 12C23 12.5304 22.7893 13.0391 22.4142 13.4142C22.0391 13.7893 21.5304 14 21 14H20.91C20.5882 14.0013 20.2738 14.0966 20.0055 14.2743C19.7372 14.452 19.5268 14.7042 19.4 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </button> </div> </header> <main> <div class="map-container"> <div class="map"> <div class="grid-lines"></div> <div class="grid-line grid-line-h"></div> <div class="grid-line grid-line-v"></div> <div class="data-pulse"></div> <div class="city-markers"> <!-- Traffic sensors --> <div class="marker traffic" style="top: 35%; left: 25%;" data-type="traffic" data-id="t1"> <div class="pulse"></div> </div> <div class="marker traffic" style="top: 60%; left: 45%;" data-type="traffic" data-id="t2"> <div class="pulse"></div> </div> <div class="marker traffic" style="top: 40%; left: 80%;" data-type="traffic" data-id="t3"> <div class="pulse"></div> </div> <!-- Energy usage sensors --> <div class="marker energy" style="top: 25%; left: 60%;" data-type="energy" data-id="e1"> <div class="pulse"></div> </div> <div class="marker energy" style="top: 70%; left: 30%;" data-type="energy" data-id="e2"> <div class="pulse"></div> </div> <!-- Public safety sensors --> <div class="marker safety" style="top: 45%; left: 52%;" data-type="safety" data-id="s1"> <div class="pulse"></div> </div> <div class="marker safety" style="top: 75%; left: 75%;" data-type="safety" data-id="s2"> <div class="pulse"></div> </div> <!-- Environmental sensors --> <div class="marker environmental" style="top: 20%; left: 40%;" data-type="environmental" data-id="env1"> <div class="pulse"></div> </div> <div class="marker environmental" style="top: 55%; left: 70%;" data-type="environmental" data-id="env2"> <div class="pulse"></div> </div> </div> <div class="info-box" id="infoBox"> <h4><span id="infoTitle">Sensor Information</span></h4> <p id="infoDescription">Hover over a sensor to view details</p> <div class="metric"> <div>Status:</div> <span id="infoStatus">-</span> </div> <div class="metric"> <div>Last update:</div> <span id="infoTime">-</span> </div> <div class="metric"> <div>Value:</div> <span id="infoValue">-</span> </div> </div> <div class="map-controls"> <div class="map-control-btn" id="zoomIn"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 5V19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </div> <div class="map-control-btn" id="zoomOut"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </div> <div class="map-control-btn" id="resetView"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M1 4V10H7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M23 20V14H
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>QuantEdge Financial Dashboard</title> <style> :root { --bg-primary: #0f1522; --bg-secondary: #1a2436; --accent-primary: #00e5ff; --accent-secondary: #fe5d54; --accent-tertiary: #7effa0; --text-primary: #f5f5f7; --text-secondary: #a0a7b5; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', 'Segoe UI', sans-serif; } body { background-color: var(--bg-primary); color: var(--text-primary); height: 700px; width: 100%; max-width: 700px; margin: 0 auto; overflow-x: hidden; } .dashboard { display: grid; grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; height: 100%; padding: 15px; gap: 15px; } header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); } .logo { font-size: 20px; font-weight: 700; background: linear-gradient(90deg, var(--accent-primary), var(--accent-tertiary)); -webkit-background-clip: text; background-clip: text; color: transparent; letter-spacing: -0.5px; } .market-status { display: flex; align-items: center; gap: 8px; } .status-indicator { width: 8px; height: 8px; border-radius: 50%; background-color: var(--accent-tertiary); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } .time { font-size: 14px; color: var(--text-secondary); } .main-content { display: grid; grid-template-columns: 1fr; grid-template-rows: auto 1fr; gap: 15px; overflow-y: auto; } .market-overview { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; } .market-card { background-color: var(--bg-secondary); border-radius: 10px; padding: 12px; transition: all 0.3s ease; cursor: pointer; position: relative; overflow: hidden; } .market-card:hover { transform: translateY(-3px); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); } .market-card::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: linear-gradient(90deg, transparent, var(--accent-primary), transparent); opacity: 0; transition: opacity 0.3s ease; } .market-card:hover::after { opacity: 1; } .market-card h3 { font-size: 14px; margin-bottom: 5px; font-weight: 500; } .market-card .price { font-size: 18px; font-weight: 700; margin-bottom: 5px; } .market-card .change { font-size: 13px; font-weight: 500; border-radius: 4px; padding: 2px 6px; display: inline-block; } .positive { background-color: rgba(126, 255, 160, 0.2); color: var(--accent-tertiary); } .negative { background-color: rgba(254, 93, 84, 0.2); color: var(--accent-secondary); } .mini-chart { margin-top: 10px; height: 40px; width: 100%; } .chart-container { background-color: var(--bg-secondary); border-radius: 10px; padding: 20px; position: relative; height: 340px; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .chart-title { font-size: 18px; font-weight: 600; } .chart-controls { display: flex; gap: 10px; } .chart-btn { background-color: rgba(255, 255, 255, 0.1); border: none; color: var(--text-secondary); padding: 6px 12px; border-radius: 6px; font-size: 12px; cursor: pointer; transition: all 0.2s ease; } .chart-btn.active { background-color: var(--accent-primary); color: var(--bg-primary); font-weight: 500; } .chart-btn:hover:not(.active) { background-color: rgba(255, 255, 255, 0.15); } #main-chart { height: 240px; width: 100%; position: relative; } .data-preview { position: absolute; background-color: rgba(26, 36, 54, 0.9); border: 1px solid var(--accent-primary); border-radius: 6px; padding: 8px 12px; font-size: 12px; color: var(--text-primary); pointer-events: none; z-index: 10; display: none; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } .data-preview p { margin: 4px 0; } .data-preview .preview-price { font-size: 14px; font-weight: 600; color: var(--accent-primary); } .ticker-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 15px; } .ticker-item { background-color: var(--bg-secondary); border-radius: 8px; padding: 10px; cursor: pointer; transition: all 0.2s ease; } .ticker-item:hover { background-color: rgba(255, 255, 255, 0.1); } .ticker-item h4 { font-size: 14px; font-weight: 500; } .ticker-item .ticker-price { font-size: 15px; font-weight: 600; margin-top: 5px; } .ticker-item .ticker-change { font-size: 12px; margin-top: 2px; } footer { display: flex; justify-content: space-between; align-items: center; padding-top: 10px; border-top: 1px solid rgba(255, 255, 255, 0.1); font-size: 12px; color: var(--text-secondary); } .refresh-rate { display: flex; align-items: center; gap: 5px; } .refresh-dot { width: 6px; height: 6px; border-radius: 50%; background-color: var(--accent-primary); animation: blink 1s infinite; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } } @media (max-width: 500px) { .market-overview { grid-template-columns: repeat(2, 1fr); } .ticker-list { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); } .chart-title { font-size: 16px; } .chart-controls { flex-wrap: wrap; } } @media (max-width: 400px) { .market-overview { grid-template-columns: 1fr; } } /* Candlestick styling */ .candle { stroke-width: 1; } .candle-up { fill: var(--accent-tertiary); stroke: var(--accent-tertiary); } .candle-down { fill: var(--accent-secondary); stroke: var(--accent-secondary); } .wick { stroke-width: 1; } .wick-up { stroke: var(--accent-tertiary); } .wick-down { stroke: var(--accent-secondary); } /* Volume bar styling */ .volume { opacity: 0.5; } .volume-up { fill: var(--accent-tertiary); } .volume-down { fill: var(--accent-secondary); } /* Line chart styling */ .line-path { fill: none; stroke: var(--accent-primary); stroke-width: 2; } .area-path { fill: url(#areaGradient); opacity: 0.2; } /* Axis styling */ .axis line, .axis path { stroke: rgba(255, 255, 255, 0.1); } .axis text { fill: var(--text-secondary); font-size: 10px; } /* Chart hover effects */ .hover-line { stroke: rgba(255, 255, 255, 0.2); stroke-width: 1; stroke-dasharray: 3,3; } .chart-overlay { fill: none; pointer-events: all; } .data-point { fill: var(--accent-primary); r: 4; opacity: 0; transition: opacity 0.2s; } .data-point.visible { opacity: 1; } </style> </head> <body> <div class="dashboard"> <header> <div class="logo">QuantEdge</div> <div class="market-status"> <div class="status-indicator"></div> <span class="time" id="market-time">NYSE: OPEN</span> </div> </header> <div class="main-content"> <div class="market-overview"> <div class="market-card" data-ticker="SPY"> <h3>S&P 500</h3> <div class="price">$478.54</div> <div class="change positive">+1.32%</div> <div class="mini-chart" id="spy-chart"></div> </div> <div class="market-card" data-ticker="QQQ"> <h3>NASDAQ 100</h3> <div class="price">$411.26</div> <div class="change positive">+1.78%</div> <div class="mini-chart" id="qqq-chart"></div> </div> <div class="market-card" data-ticker="VIX"> <h3>VIX</h3> <div class="price">17.24</div> <div class="change negative">-5.80%</div> <div class="mini-chart" id="vix-chart"></div> </div> </div> <div class="chart-container"> <div class="chart-header"> <div class="chart-title">AAPL - Apple Inc.</div> <div class="chart-controls"> <button class="chart-btn" data-timeframe="1D">1D</button> <button class="chart-btn active" data-timeframe="1W">1W</button> <button class="chart-btn" data-timeframe="1M">1M</button> <button class="chart-btn" data-timeframe="3M">3M</button> <button class="chart-btn" data-timeframe="1Y">1Y</button> </div> </div> <div id="main-chart"></div> <div class="data-preview" id="data-preview"> <p class="preview-date">Jun 10, 2023</p> <p class="preview-price">$188.47</p> <p>Open: $187.92</p> <p>High: $189.56</p> <p>Low: $187.23</p> <p>Vol: 72.8M</p> </div> </div> <div class="ticker-list"> <div class="ticker-item" data-ticker="MSFT"> <h4>MSFT</h4> <div class="ticker-price">$396.72</div> <div class="ticker-change positive">+2.14%</div> </div> <div class="ticker-item" data-ticker="AMZN"> <h4>AMZN</h4> <div class="ticker-price">$178.12</div> <div class="ticker-change positive">+1.05%</div> </div> <div class="ticker-item" data-ticker="NVDA"> <h4>NVDA</h4> <div class="ticker-price">$825.36</div> <div class="ticker-change positive">+3.78%</div> </div> <div class="ticker-item" data-ticker="GOOGL"> <h4>GOOGL</h4> <div class="ticker-price">$142.65</div> <div class="ticker-change negative">-0.54%</div> </div> </div> </div> <footer> <div>Market data delayed by at least 15 minutes</div> <div class="refresh-rate"> <div class="refresh-dot"></div> <span>Refreshing every 5s</span> </div> </footer> </div> <script src="https://d3js.org/d3.v7.min.js"></script> <script> // Initialize DOM elements document.addEventListener('DOMContentLoaded', function() { // Set current time updateMarketTime(); setInterval(updateMarketTime, 60000); // Initialize charts initMiniCharts(); initMainChart(); // Add event listeners addTickerListeners(); addChartControlListeners(); // Simulate data refresh setInterval(simulateDataRefresh, 5000); }); function updateMarketTime() { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); const timeElement = document.getElementById('market-time'); // Format time as HH:MM with leading zeros const formattedTime = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')} ET`; // Check if market is open (simplified for demo) const isMarketOpen = hours >= 9 && hours < 16; if (isMarketOpen) { timeElement.textContent = `NYSE: OPEN · ${formattedTime}`; document.querySelector('.status-indicator').style.backgroundColor = 'var(--accent-tertiary)'; } else { timeElement.textContent = `NYSE: CLOSED · ${formattedTime}`; document.querySelector('.status-indicator').style.backgroundColor = 'var(--accent-secondary)'; } } function initMiniCharts() { // Create mini charts using D3.js createMiniChart('spy-chart', generatePriceData(30, true), true); createMiniChart('qqq-chart', generatePriceData(30, true), true); createMiniChart('vix-chart', generatePriceData(30, false), false); } function createMiniChart(elementId, data, isPositive) { const container = document.getElementById(elementId); if (!container) return; const width = container.clientWidth; const height = container.clientHeight; const margin = { top: 2, right: 2, bottom: 2, left: 2 }; const svg = d3.select(`#${elementId}`) .append('svg') .attr('width', width) .attr('height', height); const x = d3.scaleLinear() .domain([0, data.length - 1]) .range([margin.left, width - margin.right]); const y = d3.scaleLinear() .domain([d3.min(data), d3.max(data)]) .range([height - margin.bottom, margin.top]); const line = d3.line() .x((d, i) => x(i)) .y(d => y(d)) .curve(d3.curveMonotoneX); const color = isPositive ? 'var(--accent-tertiary)' : 'var(--accent-secondary)'; svg.append('path') .datum(data) .attr('fill', 'none') .attr('stroke', color) .attr('stroke-width', 1.5) .attr('d', line); // Add area under the line const area = d3.area() .x((d, i) => x(i)) .y0(height - margin.bottom) .y1(d => y(d)) .curve(d3.curveMonotoneX); svg.append('path') .datum(data) .attr('fill', color) .attr('fill-opacity', 0.2) .attr('d', area); } function initMainChart() { // Set up main candlestick chart with D3.js const container = document.getElementById('main-chart'); if (!container) return; const width = container.clientWidth; const height = container.clientHeight; const margin = { top: 10, right: 10, bottom: 30, left: 40 }; const svg = d3.select('#main-chart') .append('svg') .attr('width', width) .attr('height', height); // Define gradient for area chart const defs = svg.append('defs'); const gradient = defs.append('linearGradient') .attr('id', 'areaGradient') .attr('x1', '0%') .attr('y1', '0%') .attr('x2', '0%') .attr('y2', '100%'); gradient.append('stop') .attr('offset', '0%') .attr('stop-color', 'var(--accent-primary)') .attr('stop-opacity', 0.7); gradient.append('stop') .attr('offset', '100%') .attr('stop-color', 'var(--accent-primary)') .attr('stop-opacity', 0); // Generate some random OHLC data const data = generateCandlestickData(50); // Set up scales const x = d3.scaleLinear() .domain([0, data.length - 1]) .range([margin.left, width - margin.right]); const y = d3.scaleLinear() .domain([ d3.min(data, d => d.low) * 0.999, d3.max(data, d => d.high) * 1.001 ]) .range([height - margin.bottom, margin.top]); // Add axes const xAxis = svg.append('g') .attr('class', 'axis') .attr('transform', `translate(0,${height - margin.bottom})`) .call(d3.axisBottom(x) .tickFormat(i => { // Format date for x-axis ticks const date = new Date(); date.setDate(date.getDate() - (data.length - i)); return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); }) .ticks(5) ); const yAxis = svg.append('g') .attr('class', 'axis') .attr('transform', `translate(${margin.left},0)`) .call(d3.axisLeft(y) .tickFormat(d => '$' + d.toFixed(2)) .ticks(5) ); // Add grid lines svg.append('g') .attr('class', 'grid') .attr('transform', `translate(0,${height - margin.bottom})`) .call(d3.axisBottom(x) .tickSize(-(height - margin.top - margin.bottom)) .tickFormat('') .ticks(10) ); svg.append('g') .attr('class', 'grid') .attr('transform', `translate(${margin.left},0)`) .call(d3.axisLeft(y) .tickSize(-(width - margin.left - margin.right)) .tickFormat('') .ticks(5) ); // Draw candlesticks const candleWidth = Math.min(8, (width - margin.left - margin.right) / data.length * 0.8); const candlesticks = svg.selectAll('.candle') .data(data) .enter() .append('g') .attr('class', 'candlestick'); // Add candle bodies candlesticks.append('rect') .attr('class', d => d.close >= d.open ? 'candle candle-up' : 'candle candle-down') .attr('x', (d, i) => x(i) - candleWidth / 2) .attr('y', d => d.close >= d.open ? y(d.close) : y(d.open)) .attr('width', candleWidth) .attr('height', d => Math.max(1, Math.abs(y(d.open) - y(d.close)))); // Add wicks candlesticks.append('line') .attr('class', d => d.close >= d.open ? 'wick wick-up' : 'wick wick-down') .attr('x1', (d, i) => x(i)) .attr('x2', (d, i) => x(i)) .attr('y1', d => y(d.high)) .attr('y2', d => y(d.low)); // Add interaction overlay and hover effects const overlay = svg.append('rect') .attr('class', 'chart-overlay') .attr('width', width - margin.left - margin.right) .attr('height', height - margin.top - margin.bottom) .attr('x', margin.left) .attr('y', margin.top); const hoverLine = svg.append('line') .attr('class', 'hover-line') .attr('x1', 0) .attr('x2', 0) .attr('y1', margin.top) .attr('y2', height - margin.bottom) .style('display', 'none'); const dataPreview = document.getElementById('data-preview'); overlay.on('mousemove', function(event) { const [mouseX] = d3.pointer(event); const xValue = Math.floor(x.invert(mouseX)); if (xValue >= 0 && xValue < data.length) { const d = data[xValue]; hoverLine.style('display', null) .attr('x1', x(xValue)) .attr('x2', x(xValue)); // Calculate date for display const date = new Date(); date.setDate(date.getDate() - (data.length - xValue)); const formattedDate = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); // Update preview box dataPreview.querySelector('.preview-date').textContent = formattedDate; dataPreview.querySelector('.preview-price').textContent = `$${d.close.toFixed(2)}`; dataPreview.querySelectorAll('p')[2].textContent = `Open: $${d.open.toFixed(2)}`; dataPreview.querySelectorAll('p')[3].textContent = `High: $${d.high.toFixed(2)}`; dataPreview.querySelectorAll('p')[4].textContent = `Low: $${d.low.toFixed(2)}`; dataPreview.querySelectorAll('p')[5].textContent = `Vol: ${(Math.random() * 10 + 5).toFixed(1)}M`; // Position the preview box const boxWidth = dataPreview.offsetWidth; let leftPos = x(xValue) + 10; // Ensure the box doesn't go off-screen if (leftPos + boxWidth > width - 10) { leftPos = x(xValue) - boxWidth - 10; } dataPreview.style.display = 'block'; dataPreview.style.left = `${leftPos}px`; dataPreview.style.top = `${margin.top + 10}px`; } }); overlay.on('mouseleave', function() { hoverLine.style('display', 'none'); dataPreview.style.display = 'none'; }); } function addTickerListeners() { const tickerItems = document.querySelectorAll('.ticker-item, .market-card'); tickerItems.forEach(item => { item.addEventListener('click', function() { const ticker = this.getAttribute('data-ticker'); // Change the chart title and simulate data update const chartTitle = document.querySelector('.chart-title'); const tickers = { 'MSFT': 'MSFT - Microsoft Corporation', 'AMZN': 'AMZN - Amazon.com Inc.', 'NVDA': 'NVDA - NVIDIA Corporation', 'GOOGL': 'GOOGL - Alphabet Inc.', 'SPY': 'SPY - SPDR S&P 500 ETF Trust', 'QQQ': 'QQQ - Invesco QQQ Trust', 'VIX': 'VIX - CBOE Volatility Index' }; if (ticker && tickers[ticker]) { chartTitle.textContent = tickers[ticker]; // Update chart with new data d3.select('#main-chart svg').remove(); initMainChart(); } }); }); } function addChartControlListeners() { const chartBtns = document.querySelectorAll('.chart-btn'); chartBtns.forEach(btn => { btn.addEventListener('click', function() { // Remove active class from all buttons chartBtns.forEach(b => b.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Recreate chart with adjusted data for the selected timeframe const timeframe = this.getAttribute('data-timeframe'); let dataPoints; switch(timeframe) { case '1D': dataPoints = 24; break; case '1W': dataPoints = 50; break; case '1M': dataPoints = 100; break; case '3M': dataPoints = 150; break; case '1Y': dataPoints = 200; break; default: dataPoints = 50; } // Recreate chart d3.select('#main-chart svg').remove(); initMainChart(dataPoints); }); }); } function simulateDataRefresh() { // Simulate price updates const marketCards = document.querySelectorAll('.market-card'); marketCards.forEach(card => { const priceElement = card.querySelector('.price'); const changeElement = card.querySelector('.change'); // Get current price let price = parseFloat(priceElement.textContent.replace('$', '')); // Apply a small random change const change = (Math.random() * 0.4 - 0.2) * (price * 0.01); price += change; // Format and update the price priceElement.textContent = price.toFixed(2).startsWith('$') ? price.toFixed(2) : '$' + price.toFixed(2); // Calculate and update the percentage change const percentChange = (Math.random() * 2 - 0.5).toFixed(2); changeElement.textContent = percentChange >= 0 ? `+${percentChange}%` : `${percentChange}%`; // Update the class based on the change direction if (percentChange >= 0) { changeElement.classList.remove('negative'); changeElement.classList.add('positive'); } else { changeElement.classList.remove('positive'); changeElement.classList.add('negative'); } }); // Simulate ticker updates const tickerItems = document.querySelectorAll('.ticker-item'); tickerItems.forEach(item => { const priceElement = item.querySelector('.ticker-price'); const changeElement = item.querySelector('.ticker-change'); // Get current price let price = parseFloat(priceElement.textContent.replace('$', '')); // Apply a small random change const change = (Math.random() * 0.6 - 0.3) * (price * 0.01); price += change; // Format and update the price priceElement.textContent = price.toFixed(2).startsWith('$') ? price.toFixed(2) : '$' + price.toFixed(2); // Calculate and update the percentage change const percentChange = (Math.random() * 3 - 1).toFixed(2); changeElement.textContent = percentChange >= 0 ? `+${percentChange}%` : `${percentChange}%`; // Update the class based on the change direction if (percentChange >= 0) { changeElement.classList.remove('negative'); changeElement.classList.add('positive'); } else { changeElement.classList.remove('positive'); changeElement.classList.add('negative'); } }); } // Helper functions to generate random data function generatePriceData(n, trend) { const data = []; let value = 100; for (let i = 0; i < n; i++) { const change = (Math.random() - (trend ? 0.45 : 0.55)) * 3; value += change; value = Math.max(value, 50); data.push(value); } return data; } function generateCandlestickData(n) { const data = []; let close = 180 + Math.random() * 10; for (let i = 0; i < n; i++) { const open = close; const change = (Math.random() - 0.48) * 5; close = open + change; const highExtra = Math.random() * Math.abs(change) + 0.5; const lowExtra = Math.random() * Math.abs(change) + 0.5; const high = Math.max(open, close) + highExtra; const low = Math.min(open, close) - lowExtra; data.push({ open, close, high, low }); } return data; } </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Education Progress Dashboard</title> <style> :root { --primary: #4361ee; --secondary: #3a0ca3; --accent: #7209b7; --success: #4cc9f0; --warning: #f72585; --light: #f8f9fa; --dark: #212529; --gray: #6c757d; --border-radius: 12px; --box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --transition: all 0.3s ease; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: #f5f7ff; color: var(--dark); height: 100%; overflow-x: hidden; } .dashboard { max-width: 700px; margin: 0 auto; padding: 20px; height: 700px; display: flex; flex-direction: column; overflow-y: auto; scrollbar-width: thin; } .dashboard::-webkit-scrollbar { width: 6px; } .dashboard::-webkit-scrollbar-track { background: var(--light); } .dashboard::-webkit-scrollbar-thumb { background-color: var(--gray); border-radius: 20px; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; position: sticky; top: 0; background-color: #f5f7ff; z-index: 10; padding: 10px 0; } .logo { display: flex; align-items: center; gap: 10px; } .logo-icon { width: 40px; height: 40px; background: linear-gradient(135deg, var(--primary), var(--accent)); border-radius: 10px; display: flex; align-items: center; justify-content: center; } .logo-icon i { color: white; font-size: 20px; } .logo h1 { font-size: 20px; font-weight: 600; color: var(--dark); margin: 0; } .filters { display: flex; gap: 10px; margin-bottom: 20px; } .filter-dropdown { position: relative; } .filter-btn { background-color: white; border: 1px solid #e0e0e0; border-radius: var(--border-radius); padding: 8px 15px; font-size: 14px; cursor: pointer; display: flex; align-items: center; gap: 5px; transition: var(--transition); } .filter-btn:hover { background-color: #f8f9fa; box-shadow: var(--box-shadow); } .filter-btn i { font-size: 12px; transition: var(--transition); } .filter-dropdown.active .filter-btn i { transform: rotate(180deg); } .dropdown-content { position: absolute; top: 100%; left: 0; background-color: white; min-width: 160px; box-shadow: var(--box-shadow); border-radius: var(--border-radius); z-index: 1; display: none; padding: 10px 0; margin-top: 5px; transform-origin: top center; animation: dropdown 0.2s ease; } @keyframes dropdown { from { opacity: 0; transform: scaleY(0.8); } to { opacity: 1; transform: scaleY(1); } } .filter-dropdown.active .dropdown-content { display: block; } .dropdown-item { padding: 8px 15px; cursor: pointer; transition: var(--transition); display: flex; align-items: center; gap: 5px; } .dropdown-item:hover { background-color: #f8f9fa; } .dropdown-item.active { background-color: #eef1ff; color: var(--primary); font-weight: 500; } .dropdown-item i { opacity: 0; transition: var(--transition); } .dropdown-item.active i { opacity: 1; } .stats-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-bottom: 25px; } .stat-card { background-color: white; border-radius: var(--border-radius); padding: 20px; box-shadow: var(--box-shadow); transition: var(--transition); position: relative; overflow: hidden; } .stat-card:hover { transform: translateY(-5px); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } .stat-card::before { content: ''; position: absolute; top: 0; left: 0; width: 5px; height: 100%; background: linear-gradient(to bottom, var(--primary), var(--accent)); border-top-left-radius: var(--border-radius); border-bottom-left-radius: var(--border-radius); } .stat-title { font-size: 14px; color: var(--gray); margin-bottom: 10px; } .stat-value { font-size: 28px; font-weight: 700; color: var(--dark); margin-bottom: 5px; } .stat-trend { display: flex; align-items: center; gap: 5px; font-size: 12px; } .trend-up { color: #2ecc71; } .trend-down { color: #e74c3c; } .section { background-color: white; border-radius: var(--border-radius); padding: 20px; margin-bottom: 25px; box-shadow: var(--box-shadow); } .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .section-title { font-size: 18px; font-weight: 600; color: var(--dark); display: flex; align-items: center; gap: 10px; } .section-title .icon { width: 30px; height: 30px; background: linear-gradient(135deg, var(--primary), var(--accent)); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-size: 14px; } .section-actions { display: flex; gap: 10px; } .section-btn { background-color: transparent; border: none; color: var(--gray); cursor: pointer; transition: var(--transition); font-size: 20px; } .section-btn:hover { color: var(--primary); } .tabs { display: flex; border-bottom: 1px solid #e0e0e0; margin-bottom: 20px; } .tab { padding: 10px 15px; font-size: 14px; cursor: pointer; border-bottom: 2px solid transparent; transition: var(--transition); color: var(--gray); } .tab.active { border-bottom-color: var(--primary); color: var(--primary); font-weight: 500; } .tab:hover { color: var(--dark); } .chart-container { height: 250px; margin-bottom: 20px; position: relative; } .progress-list { display: flex; flex-direction: column; gap: 15px; } .progress-item { display: flex; flex-direction: column; gap: 8px; } .progress-header { display: flex; justify-content: space-between; align-items: center; } .progress-title { font-size: 14px; font-weight: 500; } .progress-value { font-size: 14px; font-weight: 600; } .progress-bar { height: 8px; width: 100%; background-color: #e0e0e0; border-radius: 4px; overflow: hidden; position: relative; } .progress-fill { height: 100%; border-radius: 4px; transition: width 1s ease; background: linear-gradient(to right, var(--primary), var(--accent)); position: relative; overflow: hidden; } .progress-fill::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient( 90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 100% ); animation: shimmer 2s infinite; } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } .student-list { display: flex; flex-direction: column; gap: 10px; } .student-item { display: flex; align-items: center; padding: 12px; border-radius: var(--border-radius); transition: var(--transition); cursor: pointer; } .student-item:hover { background-color: #f8f9fa; } .student-avatar { width: 40px; height: 40px; border-radius: 50%; background-color: var(--primary); display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; margin-right: 15px; } .student-info { flex: 1; } .student-name { font-size: 14px; font-weight: 500; margin-bottom: 4px; } .student-details { display: flex; gap: 10px; font-size: 12px; color: var(--gray); } .student-performance { display: flex; align-items: center; gap: 10px; } .performance-indicator { width: 65px; height: 25px; background-color: #e0e0e0; border-radius: 4px; position: relative; overflow: hidden; } .performance-fill { height: 100%; position: absolute; top: 0; left: 0; transition: var(--transition); } .good { background-color: #4ade80; } .average { background-color: #fbbf24; } .poor { background-color: #f87171; } .performance-label { font-size: 12px; font-weight: 500; white-space: nowrap; } .tooltip { position: absolute; background-color: rgba(0, 0, 0, 0.8); color: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; z-index: 100; pointer-events: none; opacity: 0; transition: opacity 0.2s ease; } .tooltip::after { content: ''; position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); border-width: 5px 5px 0; border-style: solid; border-color: rgba(0, 0, 0, 0.8) transparent transparent; } @media (max-width: 600px) { .stats-grid { grid-template-columns: 1fr; } .filters { flex-wrap: wrap; } .student-details { flex-direction: column; gap: 5px; } } /* Shimmer Loading Effect */ .shimmer-effect { position: relative; overflow: hidden; background: #f6f7f8; } .shimmer-effect::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.3) 50%, rgba(255,255,255,0) 100%); animation: shimmer 2s infinite; } /* Pulse animation for stats */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse-animation { animation: pulse 2s ease infinite; } /* Innovative Features */ .floating-circle { position: absolute; width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--accent)); opacity: 0.1; z-index: -1; } .subjects-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 15px; } .subject-card { background-color: #f8f9fa; border-radius: var(--border-radius); padding: 15px; text-align: center; cursor: pointer; transition: var(--transition); border: 2px solid transparent; } .subject-card:hover { border-color: var(--primary); transform: translateY(-3px); } .subject-card.active { background-color: #eef1ff; border-color: var(--primary); } .subject-icon { font-size: 20px; margin-bottom: 8px; color: var(--primary); } .subject-name { font-size: 12px; font-weight: 500; } /* Help button */ .help-btn { position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--accent)); color: white; display: flex; align-items: center; justify-content: center; font-size: 24px; box-shadow: 0 4px 15px rgba(67, 97, 238, 0.3); cursor: pointer; transition: var(--transition); z-index: 100; } .help-btn:hover { transform: scale(1.1); } .help-tooltip { position: absolute; bottom: 60px; right: 0; background-color: white; padding: 15px; border-radius: var(--border-radius); box-shadow: var(--box-shadow); width: 200px; opacity: 0; visibility: hidden; transition: var(--transition); transform: translateY(10px); } .help-btn:hover .help-tooltip { opacity: 1; visibility: visible; transform: translateY(0); } .help-tooltip::after { content: ''; position: absolute; bottom: -8px; right: 20px; border-width: 8px 8px 0; border-style: solid; border-color: white transparent transparent; } /* Calendar mini component */ .calendar-mini { display: flex; align-items: center; gap: 10px; padding: 10px; background-color: #f8f9fa; border-radius: var(--border-radius); margin-bottom: 20px; } .calendar-date { width: 45px; height: 45px; background-color: white; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); } .date-month { font-size: 10px; color: var(--primary); font-weight: 600; text-transform: uppercase; } .date-day { font-size: 16px; font-weight: 700; } .calendar-info { flex: 1; } .calendar-title { font-size: 14px; font-weight: 500; color: var(--dark); } .calendar-subtitle { font-size: 12px; color: var(--gray); } /* Activity feed */ .activity-feed { display: flex; flex-direction: column; gap: 12px; } .activity-item { display: flex; gap: 12px; position: relative; padding-left: 20px; } .activity-item::before { content: ''; position: absolute; left: 0; top: 0; width: 2px; height: 100%; background-color: #e0e0e0; } .activity-item::after { content: ''; position: absolute; left: -4px; top: 0; width: 10px; height: 10px; border-radius: 50%; background-color: var(--primary); } .activity-content { flex: 1; background-color: #f8f9fa; border-radius: var(--border-radius); padding: 12px; } .activity-title { font-size: 14px; font-weight: 500; margin-bottom: 5px; } .activity-details { font-size: 12px; color: var(--gray); } .activity-time { font-size: 11px; color: var(--gray); white-space: nowrap; } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> </head> <body> <div class="dashboard"> <div class="header"> <div class="logo"> <div class="logo-icon"> <i class="fas fa-graduation-cap"></i> </div> <h1>EduProgress</h1> </div> <div id="currentDate">September 2023</div> </div> <div class="filters"> <div class="filter-dropdown" id="gradeFilter"> <button class="filter-btn"> <span>Grade Level</span> <i class="fas fa-chevron-down"></i> </button> <div class="dropdown-content"> <div class="dropdown-item active"><i class="fas fa-check"></i> All Grades</div> <div class="dropdown-item"><i class="fas fa-check"></i> 9th Grade</div> <div class="dropdown-item"><i class="fas fa-check"></i> 10th Grade</div> <div class="dropdown-item"><i class="fas fa-check"></i> 11th Grade</div> <div class="dropdown-item"><i class="fas fa-check"></i> 12th Grade</div> </div> </div> <div class="filter-dropdown" id="periodFilter"> <button class="filter-btn"> <span>Time Period</span> <i class="fas fa-chevron-down"></i> </button> <div class="dropdown-content"> <div class="dropdown-item active"><i class="fas fa-check"></i> Current Quarter</div> <div class="dropdown-item"><i class="fas fa-check"></i> Previous Quarter</div> <div class="dropdown-item"><i class="fas fa-check"></i> Current Semester</div> <div class="dropdown-item"><i class="fas fa-check"></i> Academic Year</div> </div> </div> <div class="filter-dropdown" id="teacherFilter"> <button class="filter-btn"> <span>Teacher</span> <i class="fas fa-chevron-down"></i> </button> <div class="dropdown-content"> <div class="dropdown-item active"><i class="fas fa-check"></i> All Teachers</div> <div class="dropdown-item"><i class="fas fa-check"></i> Ms. Johnson</div> <div class="dropdown-item"><i class="fas fa-check"></i> Mr. Rodriguez</div> <div class="dropdown-item"><i class="fas fa-check"></i> Mrs. Smith</div> <div class="dropdown-item"><i class="fas fa-check"></i> Dr. Williams</div> </div> </div> </div> <div class="calendar-mini"> <div class="calendar-date"> <div class="date-month">Sep</div> <div class="date-day">15</div> </div> <div class="calendar-info"> <div class="calendar-title">First Quarter Progress Reports Due</div> <div class="calendar-subtitle">Reminder for all faculty members</div> </div> </div> <div class="stats-grid"> <div class="stat-card"> <div class="stat-title">Average Grade</div> <div class="stat-value">84.2%</div> <div class="stat-trend trend-up"> <i class="fas fa-arrow-up"></i> <span>5.3% from last quarter</span> </div> </div> <div class="stat-card"> <div class="stat-title">Attendance Rate</div> <div class="stat-value">96.7%</div> <div class="stat-trend trend-up"> <i class="fas fa-arrow-up"></i> <span>2.1% from last month</span> </div> </div> <div class="stat-card"> <div class="stat-title">Students at Risk</div> <div class="stat-value">23</div> <div class="stat-trend trend-down"> <i class="fas fa-arrow-down"></i> <span>5 fewer than last quarter</span> </div> </div> <div class="stat-card"> <div class="stat-title">Improvement Rate</div> <div class="stat-value">72.4%</div> <div class="stat-trend trend-up"> <i class="fas fa-arrow-up"></i> <span>8.7% from previous period</span> </div> </div> </div> <div class="section"> <div class="section-header"> <div class="section-title"> <div class="icon"><i class="fas fa-book"></i></div> <span>Academic Performance</span> </div> <div class="section-actions"> <button class="section-btn"><i class="fas fa-download"></i></button> <button class="section-btn"><i class="fas fa-ellipsis-v"></i></button> </div> </div> <div class="tabs"> <div class="tab active" data-tab="performance">Performance</div> <div class="tab" data-tab="subjects">Subjects</div> <div class="tab" data-tab="trends">Trends</div> </div> <div class="tab-content" id="performanceTab"> <div class="chart-container" id="performanceChart"></div> <div class="progress-list"> <div class="progress-item"> <div class="progress-header"> <div class="progress-title">Mathematics</div> <div class="progress-value">88%</div> </div> <div class="progress-bar"> <div class="progress-fill" style="width: 88%"></div> </div> </div> <div class="progress-item"> <div class="progress-header"> <div class="progress-title">Science</div> <div class="progress-value">79%</div> </div> <div class="progress-bar"> <div class="progress-fill" style="width: 79%"></div> </div> </div> <div class="progress-item"> <div class="progress-header"> <div class="progress-title">English</div> <div class="progress-value">91%</div> </div> <div class="progress-bar"> <div class="progress-fill" style="width: 91%"></div> </div> </div> <div class="progress-item"> <div class="progress-header"> <div class="progress-title">History</div> <div class="progress-value">75%</div> </div> <div class="progress-bar"> <div class="progress-fill" style="width: 75%"></div> </div> </div> <div class="progress-item"> <div class="progress-header"> <div class="progress-title">Art & Music</div> <div class="progress-value">94%</div> </div> <div class="progress-bar"> <div class="progress-fill" style="width: 94%"></div> </div> </div> </div> </div> <div class="tab-content" id="subjectsTab" style="display: none;"> <div class="subjects-grid"> <div class="subject-card active"> <div class="subject-icon"><i class="fas fa-calculator"></i></div> <div class="subject-name">Mathematics</div> </div> <div class="subject-card"> <div class="subject-icon"><i class="fas fa-flask"></i></div> <div class="subject-name">Science</div> </div> <div class="subject-card"> <div class="subject-icon"><i class="fas fa-book"></i></div> <div class="subject-name">English</div> </div> <div class="subject-card"> <div class="subject-icon"><i class="fas fa-landmark"></i></div> <div class="subject-name">History</div> </div> <div class="subject-card"> <div class="subject-icon"><i class="fas fa-palette"></i></div> <div class="subject-name">Art</div> </div> <div class="subject-card"> <div class="subject-icon"><i class="fas fa-music"></i></div> <div class="subject-name">Music</div> </div> </div> <div class="chart-container" id="subjectDetailChart" style="margin-top: 20px;"></div> </div> <div class="tab-content" id="trendsTab" style="display: none;"> <div class="chart-container" id="trendsChart"></div> <div class="activity-feed"> <div class="activity-item"> <div class="activity-content"> <div class="activity-title">Science Scores Improved</div> <div class="activity-details">Average science scores increased by 7.2% compared to last semester</div> </div> <div class="activity-time">2 days ago</div> </div> <div class="activity-item"> <div class="activity-content"> <div class="activity-title">English Writing Workshop Impact</div> <div class="activity-details">Students who attended the workshop showed 12% higher essay scores</div> </div> <div class="activity-time">1 week ago</div> </div> <div class="activity-item"> <div class="activity-content"> <div class="activity-title">Math Tutoring Program</div> <div class="activity-details">15 students improved from below-average to above-average scores</div> </div> <div class="activity-time">2 weeks ago</div> </div> </div> </div> </div> <div class="section"> <div class="section-header"> <div class="section-title"> <div class="icon"><i class="fas fa-user-graduate"></i></div> <span>Student Spotlight</span> </div> <div class="section-actions"> <button class="section-btn"><i class="fas fa-sync-alt"></i></button> </div> </div> <div class="student-list"> <div class="student-item"> <div class="student-avatar" style="background-color: #4cc9f0;">LM</div> <div class="student-info"> <div class="student-name">Liam Martinez</div> <div class="student-details"> <span>11th Grade</span> <span>AP Physics</span> </div> </div> <div class="student-performance"> <div class="performance-indicator"> <div class="performance-fill good" style="width: 90%"></div> </div> <span class="performance-label">Excellent</span> </div> </div> <div class="student-item"> <div class="student-avatar" style="background-color: #7209b7;">SO</div> <div class="student-info"> <div class="student-name">Sophia Okonkwo</div> <div class="student-details"> <span>10th Grade</span> <span>Biology</span> </div> </div> <div class="student-performance"> <div class="performance-indicator"> <div class="performance-fill good" style="width: 85%"></div> </div> <span class="performance-label">Good</span> </div> </div> <div class="student-item"> <div class="student-avatar" style="background-color: #3a0ca3;">JC</div> <div class="student-info"> <div class="student-name">Jayden Chang</div> <div class="student-details"> <span>9th Grade</span> <span>Algebra I</span> </div> </div> <div class="student-performance"> <div class="performance-indicator"> <div class="performance-fill average" style="width: 65%"></div> </div> <span class="performance-label">Average</span> </div> </div> <div class="student-item"> <div class="student-avatar" style="background-color: #f72585;">AG</div> <div class="student-info"> <div class="student-name">Aisha Gupta</div> <div class="student-details"> <span>12th Grade</span> <span>AP Literature</span> </div> </div> <div class="student-performance"> <div class="performance-indicator"> <div class="performance-fill poor" style="width: 45%"></div> </div> <span class="performance-label">Needs Help</span> </div> </div> </div> </div> <div class="help-btn"> <i class="fas fa-question"></i> <div class="help-tooltip"> Need assistance with the dashboard? Click here to access the help guide or contact support. </div> </div> <div class="floating-circle" style="top: 120px; right: 40px;"></div> <div class="floating-circle" style="bottom: 100px; left: 30px;"></div> </div> <div class="tooltip" id="tooltip"></div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> // Current Date Display const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; const currentDate = new Date(); document.getElementById('currentDate').textContent = `${monthNames[currentDate.getMonth()]} ${currentDate.getFullYear()}`; // Dropdown Functionality const dropdowns = document.querySelectorAll('.filter-dropdown'); dropdowns.forEach(dropdown => { const button = dropdown.querySelector('.filter-btn'); button.addEventListener('click', () => { dropdown.classList.toggle('active'); // Close other dropdowns dropdowns.forEach(otherDropdown => { if (otherDropdown !== dropdown && otherDropdown.classList.contains('active')) { otherDropdown.classList.remove('active'); } }); }); // Handle dropdown item selection const items = dropdown.querySelectorAll('.dropdown-item'); items.forEach(item => { item.addEventListener('click', () => { // Remove active class from all items items.forEach(i => i.classList.remove('active')); // Add active class to clicked item item.classList.add('active'); // Update button text button.querySelector('span').textContent = item.textContent.trim().replace('✓', '').trim(); // Close dropdown dropdown.classList.remove('active'); // Trigger data refresh with animation refreshData(); }); }); // Close dropdown when clicking outside document.addEventListener('click', (event) => { if (!dropdown.contains(event.target)) { dropdown.classList.remove('active'); } }); }); // Tab Functionality const tabs = document.querySelectorAll('.tab'); const tabContents = document.querySelectorAll('.tab-content'); tabs.forEach(tab => { tab.addEventListener('click', () => { // Remove active class from all tabs tabs.forEach(t => t.classList.remove('active')); // Add active class to clicked tab tab.classList.add('active'); // Hide all tab contents tabContents.forEach(content => { content.style.display = 'none'; }); // Show selected tab content const tabId = tab.getAttribute('data-tab') + 'Tab'; document.getElementById(tabId).style.display = 'block'; // Initialize chart for
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Logistics Operations Dashboard</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', sans-serif; } :root { --primary: #2c3e50; --secondary: #34495e; --accent: #e67e22; --light: #ecf0f1; --danger: #e74c3c; --success: #27ae60; --warning: #f39c12; --info: #3498db; --dark: #1a252f; --grid-line: rgba(255, 255, 255, 0.05); } @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); body { background-color: var(--primary); color: var(--light); height: 700px; width: 700px; overflow: hidden; display: flex; flex-direction: column; } .dashboard { display: flex; flex-direction: column; height: 100%; width: 100%; padding: 15px; background-color: var(--primary); background-image: linear-gradient(rgba(26, 37, 47, 0.5) 1px, transparent 1px), linear-gradient(90deg, rgba(26, 37, 47, 0.5) 1px, transparent 1px); background-size: 20px 20px; position: relative; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid var(--grid-line); } .logo { display: flex; align-items: center; gap: 10px; } .logo svg { width: 32px; height: 32px; fill: var(--accent); } .logo h1 { font-size: 1.2rem; font-weight: 700; color: var(--light); letter-spacing: -0.5px; } .actions { display: flex; gap: 10px; } .btn { background-color: var(--secondary); color: var(--light); border: none; padding: 8px 12px; border-radius: 4px; font-weight: 500; font-size: 0.85rem; cursor: pointer; display: flex; align-items: center; gap: 5px; transition: all 0.3s ease; } .btn:hover { background-color: var(--dark); } .btn-accent { background-color: var(--accent); } .btn-accent:hover { background-color: #d35400; } .btn svg { width: 14px; height: 14px; fill: currentColor; } .main-content { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto 1fr; gap: 15px; flex: 1; overflow: hidden; } .widget { background-color: var(--secondary); border-radius: 6px; padding: 12px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); overflow: hidden; position: relative; transition: transform 0.3s ease, box-shadow 0.3s ease; } .widget:hover { transform: translateY(-2px); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); } .widget-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--grid-line); } .widget-title { font-size: 0.9rem; font-weight: 600; color: var(--light); display: flex; align-items: center; gap: 6px; } .widget-title svg { width: 14px; height: 14px; fill: var(--accent); } .widget-controls { display: flex; gap: 5px; } .widget-btn { background: none; border: none; color: var(--light); opacity: 0.6; cursor: pointer; transition: opacity 0.3s ease; } .widget-btn:hover { opacity: 1; } .widget-btn svg { width: 12px; height: 12px; fill: currentColor; } .map-widget { grid-column: 1; grid-row: 1 / span 2; display: flex; flex-direction: column; } .map-container { position: relative; flex: 1; overflow: hidden; border-radius: 4px; background-color: var(--dark); } .map-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><rect width="100" height="100" fill="%231a252f"/><path d="M0 50 L100 50" stroke="%23ecf0f130" stroke-width="0.5" stroke-dasharray="4 4"/><path d="M50 0 L50 100" stroke="%23ecf0f130" stroke-width="0.5" stroke-dasharray="4 4"/></svg>'); background-size: 20px 20px; opacity: 0.2; } .map { width: 100%; height: 100%; background-color: var(--dark); position: relative; overflow: hidden; } .route { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .route path { stroke: var(--accent); stroke-width: 2; fill: none; stroke-dasharray: 6; stroke-dashoffset: 1000; animation: dash 30s linear infinite; } @keyframes dash { to { stroke-dashoffset: 0; } } .location-marker { position: absolute; width: 10px; height: 10px; background-color: var(--accent); border-radius: 50%; transform: translate(-50%, -50%); z-index: 2; } .location-marker::after { content: ''; position: absolute; width: 20px; height: 20px; background-color: rgba(230, 126, 34, 0.3); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: translate(-50%, -50%) scale(0.5); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(2); opacity: 0; } } .hub-marker { position: absolute; width: 8px; height: 8px; background-color: var(--info); border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 0 2px var(--dark); } .shipment-list { grid-column: 2; grid-row: 1; display: flex; flex-direction: column; } .list-content { flex: 1; overflow-y: auto; margin-top: 5px; margin-right: -5px; padding-right: 5px; } .list-content::-webkit-scrollbar { width: 4px; } .list-content::-webkit-scrollbar-track { background: var(--dark); border-radius: 2px; } .list-content::-webkit-scrollbar-thumb { background: var(--accent); border-radius: 2px; } .shipment-item { display: flex; align-items: center; padding: 8px 6px; border-radius: 4px; margin-bottom: 6px; background-color: var(--dark); border-left: 3px solid transparent; transition: all 0.2s ease; cursor: pointer; } .shipment-item:hover { background-color: rgba(26, 37, 47, 0.8); transform: translateX(2px); } .shipment-item.active { border-left-color: var(--accent); background-color: rgba(230, 126, 34, 0.1); } .shipment-item.delayed { border-left-color: var(--danger); } .shipment-icon { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; margin-right: 10px; background-color: var(--secondary); border-radius: 4px; } .shipment-icon svg { width: 14px; height: 14px; fill: var(--light); } .shipment-info { flex: 1; } .shipment-id { font-size: 0.8rem; font-weight: 600; margin-bottom: 2px; color: var(--light); } .shipment-route { font-size: 0.7rem; color: var(--light); opacity: 0.7; } .shipment-status { display: flex; align-items: center; font-size: 0.7rem; font-weight: 500; padding: 2px 6px; border-radius: 10px; background-color: var(--secondary); } .status-on-route { background-color: var(--info); color: white; } .status-delayed { background-color: var(--danger); color: white; } .status-delivered { background-color: var(--success); color: white; } .stats-widget { grid-column: 2; grid-row: 2; display: flex; flex-direction: column; } .stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 5px; flex: 1; } .stat-card { background-color: var(--dark); border-radius: 4px; padding: 10px; display: flex; flex-direction: column; transition: all 0.3s ease; cursor: pointer; } .stat-card:hover { transform: scale(1.02); background-color: rgba(26, 37, 47, 0.8); } .stat-title { font-size: 0.7rem; color: var(--light); opacity: 0.7; margin-bottom: 8px; display: flex; align-items: center; gap: 4px; } .stat-title svg { width: 10px; height: 10px; fill: currentColor; } .stat-value { font-size: 1.2rem; font-weight: 700; color: var(--light); margin-bottom: 2px; } .stat-change { font-size: 0.7rem; font-weight: 500; } .stat-change.positive { color: var(--success); } .stat-change.negative { color: var(--danger); } .alert-container { position: fixed; bottom: 20px; right: 20px; width: 280px; z-index: 100; } .alert { background-color: var(--dark); border-left: 4px solid var(--warning); padding: 12px; margin-top: 10px; border-radius: 4px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); transform: translateX(120%); transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); display: flex; align-items: flex-start; gap: 10px; } .alert.show { transform: translateX(0); } .alert-icon { width: 24px; height: 24px; border-radius: 50%; background-color: var(--warning); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .alert-icon svg { width: 14px; height: 14px; fill: var(--dark); } .alert-content { flex: 1; } .alert-title { font-size: 0.85rem; font-weight: 600; margin-bottom: 4px; } .alert-message { font-size: 0.75rem; opacity: 0.9; line-height: 1.4; } .alert-close { background: none; border: none; color: var(--light); opacity: 0.6; cursor: pointer; padding: 2px; } .alert-close:hover { opacity: 1; } .alert-close svg { width: 10px; height: 10px; fill: currentColor; } .weather-info { position: absolute; bottom: 10px; left: 10px; background-color: rgba(26, 37, 47, 0.8); padding: 6px 10px; border-radius: 4px; font-size: 0.75rem; display: flex; align-items: center; gap: 6px; z-index: 10; } .weather-info svg { width: 14px; height: 14px; fill: var(--warning); } @media (max-width: 700px) { .main-content { grid-template-columns: 1fr; grid-template-rows: auto auto auto; } .map-widget { grid-column: 1; grid-row: 1; height: 200px; } .shipment-list { grid-column: 1; grid-row: 2; } .stats-widget { grid-column: 1; grid-row: 3; } } /* Animation for draggable widgets */ .widget.dragging { opacity: 0.8; z-index: 100; cursor: grabbing; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); } </style> </head> <body> <div class="dashboard"> <div class="header"> <div class="logo"> <svg viewBox="0 0 24 24"> <path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/> </svg> <h1>FleetCommand Central</h1> </div> <div class="actions"> <button class="btn"> <svg viewBox="0 0 24 24"> <path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z"/> </svg> Alerts </button> <button class="btn btn-accent" id="refresh-btn"> <svg viewBox="0 0 24 24"> <path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 9h7V2l-2.35 4.35z"/> </svg> Refresh </button> </div> </div> <div class="main-content"> <div class="widget map-widget" data-widget="map"> <div class="widget-header"> <div class="widget-title"> <svg viewBox="0 0 24 24"> <path d="M20.5 3l-.16.03L15 5.1 9 3 3.36 4.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9 18.9l6 2.1 5.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM15 19l-6-2.11V5l6 2.11V19z"/> </svg> Live Fleet Tracking </div> <div class="widget-controls"> <button class="widget-btn" title="Recenter Map"> <svg viewBox="0 0 24 24"> <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3A8.994 8.994 0 0 0 13 3.06V1h-2v2.06A8.994 8.994 0 0 0 3.06 11H1v2h2.06A8.994 8.994 0 0 0 11 20.94V23h2v-2.06A8.994 8.994 0 0 0 20.94 13H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/> </svg> </button> <button class="widget-btn" title="Toggle Traffic"> <svg viewBox="0 0 24 24"> <path d="M20 10h-3V8.86c1.72-.45 3-2 3-3.86h-3V4c0-.55-.45-1-1-1H8c-.55 0-1 .45-1 1v1H4c0 1.86 1.28 3.41 3 3.86V10H4c0 1.86 1.28 3.41 3 3.86V15H4c0 1.86 1.28 3.41 3 3.86V20c0 .55.45 1 1 1h8c.55 0 1-.45 1-1v-1.14c1.72-.45 3-2 3-3.86h-3v-1.14c1.72-.45 3-2 3-3.86zm-8 9c-1.11 0-2-.9-2-2s.89-2 2-2c1.1 0 2 .9 2 2s-.89 2-2 2zm0-5c-1.11 0-2-.9-2-2s.89-2 2-2c1.1 0 2 .9 2 2s-.89 2-2 2zm0-5c-1.11 0-2-.9-2-2 0-1.11.89-2 2-2 1.1 0 2 .89 2 2 0 1.1-.89 2-2 2z"/> </svg> </button> </div> </div> <div class="map-container"> <div class="map"> <div class="map-overlay"></div> <svg class="route" viewBox="0 0 300 200"> <path d="M30,150 C70,100 120,180 160,120 C200,60 250,90 270,40" /> </svg> <div class="location-marker" style="top: 40%; left: 50%;"></div> <div class="hub-marker" style="top: 75%; left: 15%;"></div> <div class="hub-marker" style="top: 20%; left: 90%;"></div> <div class="hub-marker" style="top: 60%; left: 60%;"></div> </div> <div class="weather-info"> <svg viewBox="0 0 24 24"> <path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"/> </svg> Route Warning: Heavy Rain on I-80 </div> </div> </div> <div class="widget shipment-list" data-widget="shipments"> <div class="widget-header"> <div class="widget-title"> <svg viewBox="0 0 24 24"> <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/> </svg> Active Shipments </div> <div class="widget-controls"> <button class="widget-btn" title="Filter"> <svg viewBox="0 0 24 24"> <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/> </svg> </button> <button class="widget-btn" title="Sort"> <svg viewBox="0 0 24 24"> <path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"/> </svg> </button> </div> </div> <div class="list-content"> <div class="shipment-item active" data-id="SH-9271"> <div class="shipment-icon"> <svg viewBox="0 0 24 24"> <path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/> </svg> </div> <div class="shipment-info"> <div class="shipment-id">SH-9271</div> <div class="shipment-route">Chicago → Denver</div> </div> <div class="shipment-status status-on-route">ON ROUTE</div> </div> <div class="shipment-item delayed" data-id="SH-8432"> <div class="shipment-icon"> <svg viewBox="0 0 24 24"> <path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/> </svg> </div> <div class="shipment-info"> <div class="shipment-id">SH-8432</div> <div class="shipment-route">Atlanta → Memphis</div> </div> <div class="shipment-status status-delayed">DELAYED</div> </div> <div class="shipment-item" data-id="SH-7103"> <div class="shipment-icon"> <svg viewBox="0 0 24 24"> <path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/> </svg> </div> <div class="shipment-info"> <div class="shipment-id">SH-7103</div> <div class="shipment-route">Dallas → Phoenix</div> </div> <div class="shipment-status status-on-route">ON ROUTE</div> </div> <div class="shipment-item" data-id="SH-6589"> <div class="shipment-icon"> <svg viewBox="0 0 24 24"> <path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/> </svg> </div> <div class="shipment-info"> <div class="shipment-id">SH-6589</div> <div class="shipment-route">Seattle → Portland</div> </div> <div class="shipment-status status-delivered">DELIVERED</div> </div> <div class="shipment-item" data-id="SH-5412"> <div class="shipment-icon"> <svg viewBox="0 0 24 24"> <path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/> </svg> </div> <div class="shipment-info"> <div class="shipment-id">SH-5412</div> <div class="shipment-route">Boston → New York</div> </div> <div class="shipment-status status-on-route">ON ROUTE</div> </div> </div> </div> <div class="widget stats-widget" data-widget="stats"> <div class="widget-header"> <div class="widget-title"> <svg viewBox="0 0 24 24"> <path d="M3.5 18.49l6-6.01 4 4L22 6.92l-1.41-1.41-7.09 7.97-4-4L2 16.99z"/> </svg> Real-time Performance </div> <div class="widget-controls"> <button class="widget-btn" title="Download Report"> <svg viewBox="0 0 24 24"> <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/> </svg> </button> </div> </div> <div class="stats-grid"> <div class="stat-card"> <div class="stat-title"> <svg viewBox="0 0 24 24"> <path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"/> </svg> On-Time Delivery </div> <div class="stat-value">92.7%</div> <div class="stat-change positive">+1.2% from last week</div> </div> <div class="stat-card"> <div class="stat-title"> <svg viewBox="0 0 24 24"> <path d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"/> </svg> Fleet Fuel Efficiency </div> <div class="stat-value">7.4 MPG</div> <div class="stat-change negative">-0.3 MPG this month</div> </div> <div class="stat-card"> <div class="stat-title"> <svg viewBox="0 0 24 24">
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Customer Support Dashboard</title> <style> :root { --primary: #5469d4; --primary-light: #7b8ce6; --secondary: #ff7d5e; --secondary-light: #ffb09e; --success: #36b37e; --warning: #ffab00; --danger: #f15252; --dark: #324054; --gray: #f7f9fc; --gray-mid: #d8dde5; --white: #ffffff; --shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --shadow-hover: 0 8px 24px rgba(0, 0, 0, 0.12); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: var(--gray); color: var(--dark); height: 700px; width: 700px; overflow: hidden; } .dashboard { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: 60px 1fr; grid-template-areas: "sidebar header" "sidebar main"; height: 100%; width: 100%; overflow: hidden; } .sidebar { grid-area: sidebar; background: var(--primary); background-image: linear-gradient(135deg, var(--primary), var(--primary-light)); color: var(--white); padding: 20px 0; overflow-y: auto; transition: var(--transition); z-index: 10; } .logo { display: flex; align-items: center; justify-content: center; margin-bottom: 20px; padding: 0 20px; } .logo svg { width: 32px; height: 32px; margin-right: 10px; } .logo h2 { font-size: 18px; font-weight: 600; } .menu { list-style: none; } .menu-item { padding: 12px 20px; display: flex; align-items: center; cursor: pointer; transition: var(--transition); border-left: 3px solid transparent; } .menu-item:hover, .menu-item.active { background: rgba(255, 255, 255, 0.1); border-left: 3px solid var(--white); } .menu-item.active { background: rgba(255, 255, 255, 0.15); } .menu-item svg { width: 18px; height: 18px; margin-right: 12px; } .header { grid-area: header; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; background: var(--white); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04); z-index: 5; } .search { position: relative; width: 260px; } .search input { width: 100%; padding: 8px 12px 8px 36px; border: 1px solid var(--gray-mid); border-radius: 20px; font-size: 14px; background: var(--gray); transition: var(--transition); } .search input:focus { outline: none; border-color: var(--primary-light); box-shadow: 0 0 0 3px rgba(84, 105, 212, 0.15); } .search svg { position: absolute; left: 12px; top: 8px; width: 16px; height: 16px; color: var(--dark); opacity: 0.6; } .user-profile { display: flex; align-items: center; } .notifications { position: relative; margin-right: 20px; cursor: pointer; } .notifications svg { width: 20px; height: 20px; } .notification-badge { position: absolute; top: -5px; right: -5px; width: 16px; height: 16px; background: var(--secondary); color: var(--white); border-radius: 50%; font-size: 10px; display: flex; align-items: center; justify-content: center; } .avatar { width: 36px; height: 36px; border-radius: 50%; background: var(--primary-light); color: var(--white); display: flex; align-items: center; justify-content: center; font-weight: 600; margin-right: 10px; cursor: pointer; } .main { grid-area: main; padding: 20px; overflow-y: auto; } .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; margin-bottom: 20px; } .stat-card { background: var(--white); border-radius: 10px; padding: 20px; box-shadow: var(--shadow); transition: var(--transition); cursor: pointer; } .stat-card:hover { box-shadow: var(--shadow-hover); transform: translateY(-2px); } .stat-card h3 { font-size: 14px; color: var(--dark); opacity: 0.7; margin-bottom: 10px; } .stat-card .value { font-size: 28px; font-weight: 700; display: flex; align-items: center; } .stat-card .trend { font-size: 12px; margin-left: 6px; display: flex; align-items: center; } .trend.up { color: var(--success); } .trend.down { color: var(--danger); } .trend svg { width: 14px; height: 14px; margin-right: 2px; } .charts-row { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 20px; } .chart-card { background: var(--white); border-radius: 10px; padding: 20px; box-shadow: var(--shadow); } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .chart-header h3 { font-size: 16px; font-weight: 600; } .chart-legend { display: flex; gap: 15px; } .legend-item { display: flex; align-items: center; font-size: 12px; } .legend-color { width: 12px; height: 12px; border-radius: 3px; margin-right: 5px; } .chart-container { height: 200px; position: relative; } .tickets-section { margin-bottom: 20px; } .tickets-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .tickets-header h3 { font-size: 16px; font-weight: 600; } .filter-tabs { display: flex; background: var(--gray); border-radius: 20px; padding: 4px; } .filter-tab { padding: 6px 16px; border-radius: 16px; font-size: 14px; cursor: pointer; transition: var(--transition); } .filter-tab.active { background: var(--white); box-shadow: var(--shadow); color: var(--primary); font-weight: 500; } .tickets-table { background: var(--white); border-radius: 10px; padding: 0; box-shadow: var(--shadow); overflow: hidden; } .table-header { display: grid; grid-template-columns: 80px 1fr 100px 120px 100px; padding: 15px 20px; background: var(--gray); border-bottom: 1px solid var(--gray-mid); font-weight: 600; font-size: 14px; } .ticket-item { display: grid; grid-template-columns: 80px 1fr 100px 120px 100px; padding: 15px 20px; border-bottom: 1px solid var(--gray-mid); align-items: center; transition: var(--transition); cursor: pointer; } .ticket-item:last-child { border-bottom: none; } .ticket-item:hover { background: rgba(84, 105, 212, 0.05); } .ticket-id { font-size: 14px; font-weight: 500; color: var(--primary); } .ticket-subject { font-size: 14px; } .ticket-priority { padding: 4px 10px; border-radius: 12px; font-size: 12px; font-weight: 500; width: fit-content; text-align: center; } .priority-high { background: rgba(241, 82, 82, 0.15); color: var(--danger); } .priority-medium { background: rgba(255, 171, 0, 0.15); color: var(--warning); } .priority-low { background: rgba(54, 179, 126, 0.15); color: var(--success); } .ticket-time { font-size: 14px; color: var(--dark); opacity: 0.7; } .ticket-status { padding: 4px 10px; border-radius: 12px; font-size: 12px; font-weight: 500; width: fit-content; text-align: center; } .status-open { background: rgba(84, 105, 212, 0.15); color: var(--primary); } .status-pending { background: rgba(255, 171, 0, 0.15); color: var(--warning); } .status-resolved { background: rgba(54, 179, 126, 0.15); color: var(--success); } .timeline-bar { width: 100%; height: 6px; background: var(--gray-mid); border-radius: 3px; overflow: hidden; margin-top: 8px; } .timeline-progress { height: 100%; border-radius: 3px; } .doughnut-container { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; } .doughnut { position: relative; width: 150px; height: 150px; } .doughnut svg { transform: rotate(-90deg); } .doughnut-segment { fill: none; stroke-width: 20; stroke-linecap: round; } .doughnut-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; } .doughnut-text .percent { font-size: 28px; font-weight: 700; color: var(--primary); } .doughnut-text .label { font-size: 12px; color: var(--dark); opacity: 0.7; } .doughnut-legend { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; } .doughnut-legend-item { display: flex; align-items: center; font-size: 13px; } .doughnut-legend-color { width: 14px; height: 14px; border-radius: 3px; margin-right: 8px; } @media (max-width: 700px) { .dashboard { grid-template-columns: 1fr; grid-template-rows: auto 60px 1fr; grid-template-areas: "header" "sidebar" "main"; } .sidebar { height: 60px; overflow-x: auto; overflow-y: hidden; padding: 0; } .logo { display: none; } .menu { display: flex; height: 100%; } .menu-item { flex-direction: column; padding: 8px 15px; border-left: none; border-bottom: 3px solid transparent; font-size: 12px; } .menu-item svg { margin-right: 0; margin-bottom: 5px; } .menu-item:hover, .menu-item.active { border-left: none; border-bottom: 3px solid var(--white); } .header { padding: 10px; } .search { width: 160px; } .user-profile { margin-left: 10px; } .stats { grid-template-columns: repeat(2, 1fr); } .charts-row { grid-template-columns: 1fr; } .table-header, .ticket-item { grid-template-columns: 80px 1fr 80px 100px; } .ticket-priority { display: none; } } /* Toast notification */ .toast { position: fixed; bottom: 20px; right: 20px; background: var(--white); color: var(--dark); padding: 12px 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); display: flex; align-items: center; transform: translateY(100px); opacity: 0; transition: all 0.3s ease; z-index: 1000; } .toast.show { transform: translateY(0); opacity: 1; } .toast-icon { margin-right: 12px; font-size: 20px; } .toast-success { border-left: 4px solid var(--success); } .toast-success .toast-icon { color: var(--success); } .toast-message { font-size: 14px; } /* Ticket modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.3s ease; } .modal.show { opacity: 1; visibility: visible; } .modal-content { background: var(--white); border-radius: 10px; width: 90%; max-width: 500px; max-height: 80vh; overflow-y: auto; transform: translateY(20px); transition: all 0.3s ease; } .modal.show .modal-content { transform: translateY(0); } .modal-header { padding: 15px 20px; border-bottom: 1px solid var(--gray-mid); display: flex; justify-content: space-between; align-items: center; } .modal-title { font-size: 18px; font-weight: 600; } .modal-close { background: none; border: none; cursor: pointer; color: var(--dark); opacity: 0.6; transition: var(--transition); } .modal-close:hover { opacity: 1; } .modal-body { padding: 20px; } .ticket-details { margin-bottom: 20px; } .ticket-details-row { display: flex; margin-bottom: 15px; } .detail-label { width: 120px; font-weight: 500; color: var(--dark); opacity: 0.7; } .detail-value { flex: 1; } .ticket-description { background: var(--gray); padding: 15px; border-radius: 8px; margin-bottom: 20px; line-height: 1.5; } .ticket-activity { margin-top: 20px; } .activity-header { font-size: 16px; font-weight: 600; margin-bottom: 15px; } .activity-item { display: flex; margin-bottom: 15px; } .activity-icon { width: 36px; height: 36px; border-radius: 50%; background: var(--gray); display: flex; align-items: center; justify-content: center; margin-right: 12px; } .activity-content { flex: 1; } .activity-title { font-weight: 500; margin-bottom: 5px; } .activity-time { font-size: 12px; color: var(--dark); opacity: 0.7; } .modal-footer { padding: 15px 20px; border-top: 1px solid var(--gray-mid); display: flex; justify-content: flex-end; gap: 10px; } .btn { padding: 8px 16px; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: var(--transition); border: none; } .btn-primary { background: var(--primary); color: var(--white); } .btn-primary:hover { background: var(--primary-light); } .btn-secondary { background: var(--gray); color: var(--dark); } .btn-secondary:hover { background: var(--gray-mid); } /* Loader animation */ .loader { width: 30px; height: 30px; border: 3px solid var(--gray-mid); border-radius: 50%; border-top-color: var(--primary); animation: spin 1s ease-in-out infinite; margin: auto; } @keyframes spin { to { transform: rotate(360deg); } } /* Ticket hover effect */ .ticket-item::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0) 70%); opacity: 0; pointer-events: none; transition: opacity 0.3s; } .ticket-item:active::after { opacity: 1; } /* Pulse notification */ @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } .notification-badge.pulse { animation: pulse 1.5s infinite; } </style> </head> <body> <div class="dashboard"> <div class="sidebar"> <div class="logo"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path> <polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline> <line x1="12" y1="22.08" x2="12" y2="12"></line> </svg> <h2>SupportHub</h2> </div> <ul class="menu"> <li class="menu-item active"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="7" height="7"></rect> <rect x="14" y="3" width="7" height="7"></rect> <rect x="14" y="14" width="7" height="7"></rect> <rect x="3" y="14" width="7" height="7"></rect> </svg> Dashboard </li> <li class="menu-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path> </svg> Tickets </li> <li class="menu-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <circle cx="9" cy="7" r="4"></circle> <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path> <path d="M16 3.13a4 4 0 0 1 0 7.75"></path> </svg> Customers </li> <li class="menu-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline> </svg> Analytics </li> <li class="menu-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="3"></circle> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> </svg> Settings </li> </ul> </div> <div class="header"> <div class="search"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> <input type="text" placeholder="Search tickets, customers..."> </div> <div class="user-profile"> <div class="notifications"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path> <path d="M13.73 21a2 2 0 0 1-3.46 0"></path> </svg> <div class="notification-badge pulse">3</div> </div> <div class="avatar">JD</div> </div> </div> <div class="main"> <div class="stats"> <div class="stat-card"> <h3>Open Tickets</h3> <div class="value">47 <span class="trend down"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>5%</span></div> </div> <div class="stat-card"> <h3>Avg. Response Time</h3> <div class="value">2.4<small>h</small> <span class="trend up"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg>10%</span></div> </div> <div class="stat-card"> <h3>CSAT Score</h3> <div class="value">4.8 <span class="trend up"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg>2%</span></div> </div> </div> <div class="charts-row"> <div class="chart-card"> <div class="chart-header"> <h3>Ticket Resolution Time</h3> <div class="chart-legend"> <div class="legend-item"> <div class="legend-color" style="background-color: var(--primary)"></div> <span>Current Week</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: var(--gray-mid)"></div> <span>Last Week</span> </div> </div> </div> <div class="chart-container" id="resolution-chart"></div> </div> <div class="chart-card"> <div class="chart-header"> <h3>Ticket Categories</h3> </div> <div class="doughnut-container"> <div class="doughnut"> <svg width="150" height="150" viewBox="0 0 150 150"> <circle class="doughnut-segment" cx="75" cy="75" r="65" stroke-dasharray="408 408" stroke-dashoffset="0" style="stroke: var(--gray-mid)"></circle> <circle class="doughnut-segment" cx="75" cy="75" r="65" stroke-dasharray="408 408" stroke-dashoffset="286" style="stroke: var(--primary)"></circle> <circle class="doughnut-segment" cx="75" cy="75" r="65" stroke-dasharray="408 408" stroke-dashoffset="327" style="stroke: var(--secondary)"></circle> <circle class="doughnut-segment" cx="75" cy="75" r="65" stroke-dasharray="408 408" stroke-dashoffset="368" style="stroke: var(--success)"></circle> </svg> <div class="doughnut-text"> <div class="percent">63%</div> <div class="label">Technical</div> </div> </div> <div class="doughnut-legend"> <div class="doughnut-legend-item"> <div class="doughnut-legend-color" style="background-color: var(--primary)"></div> <span>Technical Issues (63%)</span> </div> <div class="doughnut-legend-item"> <div class="doughnut-legend-color" style="background-color: var(--secondary)"></div> <span>Billing Queries (20%)</span> </div> <div class="doughnut-legend-item"> <div class="doughnut-legend-color" style="background-color: var(--success)"></div> <span>Feature Requests (10%)</span> </div> <div class="doughnut-legend-item"> <div class="doughnut-legend-color" style="background-color: var(--gray-mid)"></div> <span>Other (7%)</span> </div> </div> </div> </div> </div> <div class="tickets-section"> <div class="tickets-header"> <h3>Recent Tickets</h3> <div class="filter-tabs"> <div class="filter-tab active">All</div> <div class="filter-tab">Open</div> <div class="filter-tab">Pending</div> <div class="filter-tab">Resolved</div> </div> </div> <div class="tickets-table"> <div class="table-header"> <div>ID</div> <div>Subject</div> <div>Priority</div> <div>Time</div> <div>Status</div> </div> <div class="ticket-item" data-id="T-1042"> <div class="ticket-id">T-1042</div> <div class="ticket-subject">Integration with payment gateway fails</div> <div class="ticket-priority priority-high">High</div> <div class="ticket-time">1h ago</div> <div class="ticket-status status-open">Open</div> </div> <div class="ticket-item" data-id="T-1041"> <div class="ticket-id">T-1041</div> <div class="ticket-subject">Login issue after password reset</div> <div class="ticket-priority priority-medium">Medium</div> <div class="ticket-time">3h ago</div> <div class="ticket-status status-pending">Pending</div> </div> <div class="ticket-item" data-id="T-1040"> <div class="ticket-id">T-1040</div> <div class="ticket-subject">Mobile app crashes on notification</div> <div class="ticket-priority priority-high">High</div> <div class="ticket-time">5h ago</div> <div class="ticket-status status-open">Open</div> </div> <div class="ticket-item" data-id="T-1039"> <div class="ticket-id">T-1039</div> <div class="ticket-subject">Need help with API documentation</div> <div class="ticket-priority priority-low">Low</div> <div class="ticket-time">1d ago</div> <div class="ticket-status status-resolved">Resolved</div> </div> <div class="ticket-item" data-id="T-1038"> <div class="ticket-id">T-1038</div> <div class="ticket-subject">Billing cycle discrepancy in invoice</div> <div class="ticket-priority priority-medium">Medium</div>