Spaces:
Sleeping
Sleeping
colors
Browse files- src/components/charts.ts +38 -4
- src/style.css +26 -16
src/components/charts.ts
CHANGED
|
@@ -49,7 +49,7 @@ function getACWRColor(value: number | null): string {
|
|
| 49 |
hue = HUE_RED;
|
| 50 |
}
|
| 51 |
|
| 52 |
-
return `hsla(${hue}, 85%,
|
| 53 |
}
|
| 54 |
|
| 55 |
// Plugin to draw gradient-colored ACWR line
|
|
@@ -87,7 +87,7 @@ const acwrGradientPlugin = {
|
|
| 87 |
|
| 88 |
const color = getACWRColor(segmentValue);
|
| 89 |
// Make the fill more transparent
|
| 90 |
-
const fillColor = color.replace(/[\d.]+\)$/, '0.
|
| 91 |
|
| 92 |
ctx.fillStyle = fillColor;
|
| 93 |
ctx.beginPath();
|
|
@@ -134,6 +134,36 @@ const acwrGradientPlugin = {
|
|
| 134 |
// Register the custom plugin
|
| 135 |
Chart.register(acwrGradientPlugin);
|
| 136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
// Function to get activity emoji based on type
|
| 138 |
function getActivityEmoji(activityType: string): string {
|
| 139 |
const type = activityType.toLowerCase();
|
|
@@ -307,6 +337,7 @@ const commonOptions = {
|
|
| 307 |
font: {
|
| 308 |
size: 12,
|
| 309 |
},
|
|
|
|
| 310 |
},
|
| 311 |
},
|
| 312 |
tooltip: {
|
|
@@ -524,7 +555,10 @@ function createDualAxisChart(
|
|
| 524 |
},
|
| 525 |
ticks: {
|
| 526 |
padding: 8,
|
| 527 |
-
color:
|
|
|
|
|
|
|
|
|
|
| 528 |
font: {
|
| 529 |
size: 11,
|
| 530 |
},
|
|
@@ -532,7 +566,7 @@ function createDualAxisChart(
|
|
| 532 |
title: {
|
| 533 |
display: true,
|
| 534 |
text: 'ACWR',
|
| 535 |
-
color: '#
|
| 536 |
font: {
|
| 537 |
size: 12,
|
| 538 |
weight: 500,
|
|
|
|
| 49 |
hue = HUE_RED;
|
| 50 |
}
|
| 51 |
|
| 52 |
+
return `hsla(${hue}, 85%, 65%, 0.99)`;
|
| 53 |
}
|
| 54 |
|
| 55 |
// Plugin to draw gradient-colored ACWR line
|
|
|
|
| 87 |
|
| 88 |
const color = getACWRColor(segmentValue);
|
| 89 |
// Make the fill more transparent
|
| 90 |
+
const fillColor = color.replace(/[\d.]+\)$/, '0.25)');
|
| 91 |
|
| 92 |
ctx.fillStyle = fillColor;
|
| 93 |
ctx.beginPath();
|
|
|
|
| 134 |
// Register the custom plugin
|
| 135 |
Chart.register(acwrGradientPlugin);
|
| 136 |
|
| 137 |
+
// Plugin to color y1 (ACWR) axis labels with gradient colors
|
| 138 |
+
const acwrAxisColorPlugin = {
|
| 139 |
+
id: 'acwrAxisColor',
|
| 140 |
+
afterDraw(chart: Chart) {
|
| 141 |
+
const y1Scale = chart.scales['y1'];
|
| 142 |
+
if (!y1Scale) return;
|
| 143 |
+
|
| 144 |
+
const ctx = chart.ctx;
|
| 145 |
+
ctx.save();
|
| 146 |
+
|
| 147 |
+
// Get the tick values and positions
|
| 148 |
+
const ticks = y1Scale.ticks;
|
| 149 |
+
ticks.forEach((tick: any) => {
|
| 150 |
+
const value = tick.value;
|
| 151 |
+
const color = getACWRColor(value);
|
| 152 |
+
|
| 153 |
+
// Find the tick label element and color it
|
| 154 |
+
const tickLabel = y1Scale.getPixelForValue(value);
|
| 155 |
+
if (tickLabel !== undefined) {
|
| 156 |
+
ctx.fillStyle = color;
|
| 157 |
+
}
|
| 158 |
+
});
|
| 159 |
+
|
| 160 |
+
ctx.restore();
|
| 161 |
+
},
|
| 162 |
+
};
|
| 163 |
+
|
| 164 |
+
// Register the axis color plugin
|
| 165 |
+
Chart.register(acwrAxisColorPlugin);
|
| 166 |
+
|
| 167 |
// Function to get activity emoji based on type
|
| 168 |
function getActivityEmoji(activityType: string): string {
|
| 169 |
const type = activityType.toLowerCase();
|
|
|
|
| 337 |
font: {
|
| 338 |
size: 12,
|
| 339 |
},
|
| 340 |
+
color: '#94a3b8',
|
| 341 |
},
|
| 342 |
},
|
| 343 |
tooltip: {
|
|
|
|
| 555 |
},
|
| 556 |
ticks: {
|
| 557 |
padding: 8,
|
| 558 |
+
color: (context: any) => {
|
| 559 |
+
// Color each tick based on its value using ACWR gradient
|
| 560 |
+
return getACWRColor(context.tick.value);
|
| 561 |
+
},
|
| 562 |
font: {
|
| 563 |
size: 11,
|
| 564 |
},
|
|
|
|
| 566 |
title: {
|
| 567 |
display: true,
|
| 568 |
text: 'ACWR',
|
| 569 |
+
color: '#4ade80',
|
| 570 |
font: {
|
| 571 |
size: 12,
|
| 572 |
weight: 500,
|
src/style.css
CHANGED
|
@@ -1,14 +1,14 @@
|
|
| 1 |
:root {
|
| 2 |
-
--primary-color: #
|
| 3 |
-
--secondary-color: #
|
| 4 |
-
--success-color: #
|
| 5 |
-
--warning-color: #
|
| 6 |
-
--danger-color: #
|
| 7 |
-
--bg-color: #
|
| 8 |
-
--card-bg: #
|
| 9 |
-
--text-color: #
|
| 10 |
-
--border-color: #
|
| 11 |
-
--optimal-color: rgba(
|
| 12 |
}
|
| 13 |
|
| 14 |
* {
|
|
@@ -327,21 +327,26 @@ h2 {
|
|
| 327 |
}
|
| 328 |
|
| 329 |
#ftp-input,
|
| 330 |
-
#target-acwr-input
|
|
|
|
|
|
|
| 331 |
width: 70px;
|
| 332 |
padding: 0.375rem 0.5rem;
|
| 333 |
border: 1px solid var(--border-color);
|
| 334 |
border-radius: 4px;
|
| 335 |
font-size: 0.875rem;
|
| 336 |
text-align: center;
|
| 337 |
-
background-color:
|
|
|
|
| 338 |
}
|
| 339 |
|
| 340 |
#ftp-input:focus,
|
| 341 |
-
#target-acwr-input:focus
|
|
|
|
|
|
|
| 342 |
outline: none;
|
| 343 |
border-color: var(--primary-color);
|
| 344 |
-
box-shadow: 0 0 0 2px rgba(
|
| 345 |
}
|
| 346 |
|
| 347 |
.ftp-unit {
|
|
@@ -459,10 +464,15 @@ h2 {
|
|
| 459 |
}
|
| 460 |
|
| 461 |
.chart-container {
|
| 462 |
-
background-color:
|
| 463 |
border-radius: 8px;
|
| 464 |
padding: 1.5rem;
|
| 465 |
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
}
|
| 467 |
|
| 468 |
.chart-container canvas {
|
|
|
|
| 1 |
:root {
|
| 2 |
+
--primary-color: #60a5fa;
|
| 3 |
+
--secondary-color: #94a3b8;
|
| 4 |
+
--success-color: #34d399;
|
| 5 |
+
--warning-color: #fbbf24;
|
| 6 |
+
--danger-color: #f87171;
|
| 7 |
+
--bg-color: #1e1e1e;
|
| 8 |
+
--card-bg: #2d2d2d;
|
| 9 |
+
--text-color: #e5e7eb;
|
| 10 |
+
--border-color: #404040;
|
| 11 |
+
--optimal-color: rgba(52, 211, 153, 0.2);
|
| 12 |
}
|
| 13 |
|
| 14 |
* {
|
|
|
|
| 327 |
}
|
| 328 |
|
| 329 |
#ftp-input,
|
| 330 |
+
#target-acwr-input,
|
| 331 |
+
#threshold-hr-input,
|
| 332 |
+
#resting-hr-input {
|
| 333 |
width: 70px;
|
| 334 |
padding: 0.375rem 0.5rem;
|
| 335 |
border: 1px solid var(--border-color);
|
| 336 |
border-radius: 4px;
|
| 337 |
font-size: 0.875rem;
|
| 338 |
text-align: center;
|
| 339 |
+
background-color: #3a3a3a;
|
| 340 |
+
color: var(--text-color);
|
| 341 |
}
|
| 342 |
|
| 343 |
#ftp-input:focus,
|
| 344 |
+
#target-acwr-input:focus,
|
| 345 |
+
#threshold-hr-input:focus,
|
| 346 |
+
#resting-hr-input:focus {
|
| 347 |
outline: none;
|
| 348 |
border-color: var(--primary-color);
|
| 349 |
+
box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.2);
|
| 350 |
}
|
| 351 |
|
| 352 |
.ftp-unit {
|
|
|
|
| 464 |
}
|
| 465 |
|
| 466 |
.chart-container {
|
| 467 |
+
background-color: #00000075;
|
| 468 |
border-radius: 8px;
|
| 469 |
padding: 1.5rem;
|
| 470 |
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
| 471 |
+
}
|
| 472 |
+
|
| 473 |
+
.chart-container h2 {
|
| 474 |
+
color: #fbfefe;
|
| 475 |
+
margin-bottom: 1rem;
|
| 476 |
}
|
| 477 |
|
| 478 |
.chart-container canvas {
|