diff --git a/assets/css/app.css b/assets/css/app.css index bef2604..5b6d3ee 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -378,6 +378,7 @@ button { .dashboard-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); + align-items: start; } .chart-card--calendar, @@ -474,9 +475,12 @@ button { stroke-width: 1.1; } -.line-chart, +.line-chart { + min-height: 10.25rem; +} + .bar-chart { - min-height: 17rem; + min-height: 11rem; } .line-chart svg { @@ -499,16 +503,35 @@ button { stroke-width: 1.5; } +.line-point--solo { + stroke-width: 2; +} + +.line-point-glow { + opacity: 0.16; +} + .chart-axis { stroke: rgba(255, 255, 255, 0.1); stroke-width: 1; } +.chart-guide { + opacity: 0.22; + stroke-width: 2; +} + .chart-label { fill: rgba(239, 247, 255, 0.65); font-size: 11px; } +.chart-value { + fill: rgba(239, 247, 255, 0.9); + font-size: 15px; + font-weight: 700; +} + .bar-chart svg { width: 100%; height: auto; @@ -987,6 +1010,14 @@ input[type="range"] { flex-direction: column; align-items: flex-start; } + + .line-chart { + min-height: 9.5rem; + } + + .bar-chart { + min-height: 10rem; + } } @media (max-width: 640px) { @@ -1011,4 +1042,16 @@ input[type="range"] { .hero-score { font-size: 2.8rem; } + + .chart-card { + padding: 1rem; + } + + .line-chart { + min-height: 8.75rem; + } + + .bar-chart { + min-height: 9.5rem; + } } diff --git a/assets/js/app.js b/assets/js/app.js index e96f0e4..b45b75e 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,5 +1,6 @@ (function () { const textDecoder = new TextDecoder(); + let dashboardResizeTimer = null; function decodePayload(raw) { if (!raw) { @@ -282,11 +283,55 @@ return; } + const seriesName = container.dataset.series || ""; + const values = items.map(item => Number(item.value)); const width = 760; - const height = 220; - const padding = { top: 18, right: 18, bottom: 38, left: 14 }; - const maxValue = Math.max(...items.map(item => Number(item.value)), 10); - const minValue = 0; + const height = 196; + const padding = { top: 10, right: 18, bottom: 28, left: 14 }; + let minValue = Math.min(...values); + let maxValue = Math.max(...values); + + if (seriesName === "mood" || seriesName === "stress") { + minValue = Math.max(1, minValue - 1.5); + maxValue = Math.min(10, maxValue + 1.5); + } else { + minValue = Math.max(0, minValue - 1); + maxValue = maxValue + 1; + } + + if ((maxValue - minValue) < 3) { + const center = (maxValue + minValue) / 2; + if (seriesName === "mood" || seriesName === "stress") { + minValue = Math.max(1, center - 1.5); + maxValue = Math.min(10, center + 1.5); + } else { + minValue = Math.max(0, center - 1.5); + maxValue = center + 1.5; + } + } + + if (items.length === 1) { + const only = items[0]; + const chartTop = padding.top; + const chartBottom = height - padding.bottom; + const ratio = (Number(only.value) - minValue) / Math.max(maxValue - minValue, 1); + const cx = width / 2; + const cy = chartTop + ((1 - ratio) * (chartBottom - chartTop)); + + container.innerHTML = ` + + `; + return; + } + const step = items.length > 1 ? (width - padding.left - padding.right) / (items.length - 1) : 0; const points = items.map((item, index) => { @@ -324,9 +369,9 @@ const recent = items.slice(-18); const maxValue = Math.max(...recent.map(item => Number(item.value)), 1); const width = Math.max(recent.length * 34, 520); - const height = 220; - const chartHeight = 150; - const baseY = 176; + const height = 184; + const chartHeight = 118; + const baseY = 146; const bars = recent.map((item, index) => { const sport = Number(item.sport || 0); @@ -349,7 +394,7 @@