mobile friendliness
This commit is contained in:
parent
373018cebb
commit
d775dea0dc
@ -51,6 +51,8 @@
|
|||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e0e0e0;
|
||||||
|
position: relative;
|
||||||
|
min-height: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-container h3 {
|
.chart-container h3 {
|
||||||
@ -61,25 +63,83 @@
|
|||||||
|
|
||||||
.chart-container canvas {
|
.chart-container canvas {
|
||||||
height: 300px !important;
|
height: 300px !important;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100% !important;
|
||||||
|
touch-action: pan-y; /* Allow vertical scrolling on mobile */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive design */
|
/* Responsive design */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
.dashboard-container {
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard-cards {
|
.dashboard-cards {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-charts {
|
.dashboard-charts {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-card {
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-value {
|
.card-value {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
padding: 1rem;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container canvas {
|
||||||
|
height: 250px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
|
.dashboard-container {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard-cards {
|
.dashboard-cards {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-card {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-card h3 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-value {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-subtitle {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
padding: 0.75rem;
|
||||||
|
min-height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container canvas {
|
||||||
|
height: 200px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,9 @@ function createSupportLevelChart(supportLevels) {
|
|||||||
supportChart.destroy();
|
supportChart.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if mobile
|
||||||
|
const isMobile = window.innerWidth <= 480;
|
||||||
|
|
||||||
supportChart = new Chart(ctx, {
|
supportChart = new Chart(ctx, {
|
||||||
type: 'doughnut',
|
type: 'doughnut',
|
||||||
data: {
|
data: {
|
||||||
@ -62,7 +65,26 @@ function createSupportLevelChart(supportLevels) {
|
|||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
position: 'bottom'
|
position: isMobile ? 'bottom' : 'bottom',
|
||||||
|
labels: {
|
||||||
|
padding: isMobile ? 10 : 20,
|
||||||
|
font: {
|
||||||
|
size: isMobile ? 10 : 12
|
||||||
|
},
|
||||||
|
usePointStyle: true,
|
||||||
|
pointStyle: 'circle'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
const label = context.label || '';
|
||||||
|
const value = context.parsed || 0;
|
||||||
|
const total = context.dataset.data.reduce((a, b) => a + b, 0);
|
||||||
|
const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : 0;
|
||||||
|
return `${label}: ${value} (${percentage}%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,6 +100,10 @@ function createEntriesChart(dailyEntries) {
|
|||||||
entriesChart.destroy();
|
entriesChart.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if mobile
|
||||||
|
const isMobile = window.innerWidth <= 480;
|
||||||
|
const isTablet = window.innerWidth <= 768;
|
||||||
|
|
||||||
// Generate last 30 days
|
// Generate last 30 days
|
||||||
const labels = [];
|
const labels = [];
|
||||||
const data = [];
|
const data = [];
|
||||||
@ -87,7 +113,16 @@ function createEntriesChart(dailyEntries) {
|
|||||||
const date = new Date(today);
|
const date = new Date(today);
|
||||||
date.setDate(date.getDate() - i);
|
date.setDate(date.getDate() - i);
|
||||||
const dateKey = date.toISOString().split('T')[0];
|
const dateKey = date.toISOString().split('T')[0];
|
||||||
labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));
|
|
||||||
|
// Format labels based on screen size
|
||||||
|
if (isMobile) {
|
||||||
|
labels.push(date.toLocaleDateString('en-US', { day: 'numeric' }));
|
||||||
|
} else if (isTablet) {
|
||||||
|
labels.push(date.toLocaleDateString('en-US', { month: 'numeric', day: 'numeric' }));
|
||||||
|
} else {
|
||||||
|
labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));
|
||||||
|
}
|
||||||
|
|
||||||
data.push(dailyEntries[dateKey] || 0);
|
data.push(dailyEntries[dateKey] || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,17 +135,65 @@ function createEntriesChart(dailyEntries) {
|
|||||||
data: data,
|
data: data,
|
||||||
borderColor: 'rgb(75, 192, 192)',
|
borderColor: 'rgb(75, 192, 192)',
|
||||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||||
tension: 0.1
|
tension: 0.1,
|
||||||
|
fill: true,
|
||||||
|
pointRadius: isMobile ? 2 : 3,
|
||||||
|
pointHoverRadius: isMobile ? 4 : 5
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
|
interaction: {
|
||||||
|
intersect: false,
|
||||||
|
mode: 'index'
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: !isMobile,
|
||||||
|
labels: {
|
||||||
|
font: {
|
||||||
|
size: isMobile ? 10 : 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
title: function(context) {
|
||||||
|
const index = context[0].dataIndex;
|
||||||
|
const date = new Date(today);
|
||||||
|
date.setDate(date.getDate() - (29 - index));
|
||||||
|
return date.toLocaleDateString('en-US', {
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
year: 'numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
scales: {
|
scales: {
|
||||||
|
x: {
|
||||||
|
ticks: {
|
||||||
|
maxTicksLimit: isMobile ? 6 : isTablet ? 10 : 15,
|
||||||
|
font: {
|
||||||
|
size: isMobile ? 9 : 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
display: !isMobile
|
||||||
|
}
|
||||||
|
},
|
||||||
y: {
|
y: {
|
||||||
beginAtZero: true,
|
beginAtZero: true,
|
||||||
ticks: {
|
ticks: {
|
||||||
stepSize: 1
|
stepSize: 1,
|
||||||
|
font: {
|
||||||
|
size: isMobile ? 9 : 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.1)'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,4 +230,45 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
loadDashboardData();
|
loadDashboardData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle window resize for chart responsiveness
|
||||||
|
let resizeTimeout;
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
clearTimeout(resizeTimeout);
|
||||||
|
resizeTimeout = setTimeout(() => {
|
||||||
|
// Only refresh charts if dashboard is visible
|
||||||
|
const dashboardSection = document.getElementById('dashboard');
|
||||||
|
if (dashboardSection && dashboardSection.style.display !== 'none') {
|
||||||
|
// Refresh charts with current data
|
||||||
|
if (supportChart) {
|
||||||
|
const currentData = supportChart.data.datasets[0].data;
|
||||||
|
const supportLevels = {
|
||||||
|
'1': currentData[0] || 0,
|
||||||
|
'2': currentData[1] || 0,
|
||||||
|
'3': currentData[2] || 0,
|
||||||
|
'4': currentData[3] || 0
|
||||||
|
};
|
||||||
|
createSupportLevelChart(supportLevels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entriesChart) {
|
||||||
|
const currentLabels = entriesChart.data.labels;
|
||||||
|
const currentData = entriesChart.data.datasets[0].data;
|
||||||
|
|
||||||
|
// Reconstruct dailyEntries object from current chart data
|
||||||
|
const dailyEntries = {};
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
|
currentData.forEach((value, index) => {
|
||||||
|
const date = new Date(today);
|
||||||
|
date.setDate(date.getDate() - (29 - index));
|
||||||
|
const dateKey = date.toISOString().split('T')[0];
|
||||||
|
dailyEntries[dateKey] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
createEntriesChart(dailyEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user