anaylitics dashboard

This commit is contained in:
2025-07-30 09:04:21 -06:00
parent 2312d87b2d
commit 9689767d6c
9 changed files with 393 additions and 0 deletions

View File

@@ -43,6 +43,10 @@
<button id="close-sidebar" class="close-sidebar">×</button>
</div>
<nav class="admin-nav">
<a href="#dashboard">
<span class="nav-icon">📊</span>
<span class="nav-text">Dashboard</span>
</a>
<a href="#start-location" class="active">
<span class="nav-icon">📍</span>
<span class="nav-text">Start Location</span>
@@ -66,6 +70,47 @@
</div>
<div class="admin-content">
<!-- Dashboard Section -->
<section id="dashboard" class="admin-section" style="display: none;">
<h2>Campaign Dashboard</h2>
<p>Overview of campaign metrics and statistics</p>
<div class="dashboard-container">
<!-- Summary Cards -->
<div class="dashboard-cards">
<div class="dashboard-card">
<h3>Total Locations</h3>
<div class="card-value" id="total-locations">-</div>
</div>
<div class="dashboard-card">
<h3>Overall Score</h3>
<div class="card-value" id="overall-score">-</div>
<div class="card-subtitle">out of 4.0</div>
</div>
<div class="dashboard-card">
<h3>Sign Requests</h3>
<div class="card-value" id="sign-requests">-</div>
</div>
<div class="dashboard-card">
<h3>Total Users</h3>
<div class="card-value" id="total-users">-</div>
</div>
</div>
<!-- Charts -->
<div class="dashboard-charts">
<div class="chart-container">
<h3>Support Level Distribution</h3>
<canvas id="support-chart"></canvas>
</div>
<div class="chart-container">
<h3>Daily Entries (Last 30 Days)</h3>
<canvas id="entries-chart"></canvas>
</div>
</div>
</div>
</section>
<!-- Start Location Section -->
<section id="start-location" class="admin-section">
<h2>Map Start Location</h2>
@@ -372,6 +417,12 @@
<!-- Cache Management -->
<script src="js/cache-manager.js"></script>
<!-- Chart.js library -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<!-- Dashboard JavaScript -->
<script src="js/dashboard.js"></script>
<!-- Admin JavaScript -->
<script src="js/admin.js"></script>
</body>

View File

@@ -1,4 +1,6 @@
/* Admin Panel Specific Styles */
@import url("modules/dashboard.css");
.admin-container {
display: flex;
height: calc(100vh - var(--header-height));

View File

@@ -0,0 +1,85 @@
/* Dashboard Styles */
.dashboard-container {
display: flex;
flex-direction: column;
gap: 2rem;
}
.dashboard-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}
.dashboard-card {
background: white;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
border: 1px solid #e0e0e0;
}
.dashboard-card h3 {
margin: 0 0 1rem 0;
font-size: 1rem;
color: #666;
font-weight: 500;
}
.card-value {
font-size: 2.5rem;
font-weight: 700;
color: var(--primary-color);
}
.card-subtitle {
font-size: 0.875rem;
color: #999;
margin-top: 0.5rem;
}
.dashboard-charts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 2rem;
}
.chart-container {
background: white;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border: 1px solid #e0e0e0;
}
.chart-container h3 {
margin: 0 0 1.5rem 0;
font-size: 1.25rem;
color: #333;
}
.chart-container canvas {
height: 300px !important;
}
/* Responsive design */
@media (max-width: 768px) {
.dashboard-cards {
grid-template-columns: repeat(2, 1fr);
}
.dashboard-charts {
grid-template-columns: 1fr;
}
.card-value {
font-size: 2rem;
}
}
@media (max-width: 480px) {
.dashboard-cards {
grid-template-columns: 1fr;
}
}

View File

@@ -0,0 +1,150 @@
// Dashboard functionality
let supportChart = null;
let entriesChart = null;
// Load dashboard data
async function loadDashboardData() {
try {
const response = await fetch('/api/admin/dashboard/stats');
const result = await response.json();
if (result.success) {
updateDashboardCards(result.data);
createSupportLevelChart(result.data.supportLevels);
createEntriesChart(result.data.dailyEntries);
} else {
showStatus('Failed to load dashboard data', 'error');
}
} catch (error) {
console.error('Dashboard loading error:', error);
showStatus('Error loading dashboard', 'error');
}
}
// Update summary cards
function updateDashboardCards(data) {
document.getElementById('total-locations').textContent = data.totalLocations.toLocaleString();
document.getElementById('overall-score').textContent = data.overallScore;
document.getElementById('sign-requests').textContent = data.signRequests.toLocaleString();
document.getElementById('total-users').textContent = data.totalUsers.toLocaleString();
}
// Create support level distribution chart
function createSupportLevelChart(supportLevels) {
const ctx = document.getElementById('support-chart');
if (!ctx) return;
if (supportChart) {
supportChart.destroy();
}
supportChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Strong Support (1)', 'Support (2)', 'Neutral (3)', 'Opposed (4)'],
datasets: [{
data: [
supportLevels['1'] || 0,
supportLevels['2'] || 0,
supportLevels['3'] || 0,
supportLevels['4'] || 0
],
backgroundColor: [
'#4CAF50',
'#FFC107',
'#FF9800',
'#F44336'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
}
// Create daily entries chart
function createEntriesChart(dailyEntries) {
const ctx = document.getElementById('entries-chart');
if (!ctx) return;
if (entriesChart) {
entriesChart.destroy();
}
// Generate last 30 days
const labels = [];
const data = [];
const today = new Date();
for (let i = 29; i >= 0; i--) {
const date = new Date(today);
date.setDate(date.getDate() - i);
const dateKey = date.toISOString().split('T')[0];
labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));
data.push(dailyEntries[dateKey] || 0);
}
entriesChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'New Entries',
data: data,
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
tension: 0.1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
}
// Add event listener for dashboard navigation
document.addEventListener('DOMContentLoaded', () => {
// Update navigation to load dashboard when clicked
const dashboardLink = document.querySelector('.admin-nav a[href="#dashboard"]');
if (dashboardLink) {
dashboardLink.addEventListener('click', (e) => {
e.preventDefault();
// Hide all sections
document.querySelectorAll('.admin-section').forEach(section => {
section.style.display = 'none';
});
// Show dashboard
const dashboardSection = document.getElementById('dashboard');
if (dashboardSection) {
dashboardSection.style.display = 'block';
}
// Update active nav
document.querySelectorAll('.admin-nav a').forEach(link => {
link.classList.remove('active');
});
dashboardLink.classList.add('active');
// Load dashboard data
loadDashboardData();
});
}
});