Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,039 changes: 840 additions & 199 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions assets/_component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,11 @@ ul.results {
span {
text-align: center;
}

.ath {
cursor: pointer;
text-decoration: underline dotted;
}
}

.exercise-edit>.input-row {
Expand Down
26 changes: 26 additions & 0 deletions assets/_unique.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,32 @@
}
}

fieldset.analytics-mode {
margin: 0 auto var(--spacing) auto;
max-width: var(--column);
border: none;
padding: 0;

legend {
margin-bottom: calc(var(--spacing) / 2);
font-size: 0.9rem;
color: var(--secondary);
}

.mode-options {
display: flex;
gap: var(--spacing);
flex-wrap: wrap;

label {
display: flex;
align-items: center;
gap: calc(var(--spacing) / 4);
cursor: pointer;
}
}
}

main.analytics {
padding: 0;

Expand Down
5 changes: 5 additions & 0 deletions assets/en.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ notif-rest-body = Time to start your next set!
## Analytics page
analytics-title = 📊 Analytics
analytics-subtitle = Track your progress over time
analytics-mode-label = Analytics Mode
analytics-mode-set = Set
analytics-mode-session-avg = Session Avg
analytics-mode-session-total = Session Total
analytics-volume-exercise-label = -- Volume Exercise --
analytics-pairs-label = Metric–Exercise Pairs (⩽ 8)
analytics-empty = Select exercises to view analytics
analytics-metric-weight = Weight (kg)
Expand Down
5 changes: 5 additions & 0 deletions assets/es.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ notif-rest-body = ¡Es hora de tu próxima serie!
## Página de estadísticas
analytics-title = 📊 Estadísticas
analytics-subtitle = Sigue tu progreso a lo largo del tiempo
analytics-mode-label = Modo estadísticas
analytics-mode-set = Serie
analytics-mode-session-avg = Prom. sesión
analytics-mode-session-total = Total sesión
analytics-volume-exercise-label = -- Ejercicio de volumen --
analytics-pairs-label = Pares métrica–ejercicio (⩽ 8)
analytics-empty = Selecciona ejercicios para ver las estadísticas
analytics-metric-weight = Peso (kg)
Expand Down
5 changes: 5 additions & 0 deletions assets/fr.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ notif-rest-body = C'est l'heure de ta prochaine série !
## Page Statistiques
analytics-title = 📊 Statistiques
analytics-subtitle = Suis ta progression dans le temps
analytics-mode-label = Mode statistiques
analytics-mode-set = Série
analytics-mode-session-avg = Moy. séance
analytics-mode-session-total = Total séance
analytics-volume-exercise-label = -- Exercice volume --
analytics-pairs-label = Paires métrique–exercice (⩽ 8)
analytics-empty = Sélectionnez des exercices pour voir les statistiques
analytics-metric-weight = Poids (kg)
Expand Down
18 changes: 9 additions & 9 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@
};
wasm-bindgen-cli = rustPlatform.buildRustPackage rec {
pname = "wasm-bindgen-cli";
version = "0.2.118";
version = "0.2.120";
src = pkgs.fetchCrate {
inherit pname version;
hash = "sha256-ve783oYH0TGv8Z8lIPdGjItzeLDQLOT5uv/jbFOlZpI=";
hash = "sha256-Dkkx8Bhfk+y/jEz9Fzwytmv2N3Gj/7ST+5MlPRzzetU=";
# hash = pkgs.lib.fakeHash;
};
cargoHash = "sha256-EYDfuBlH3zmTxACBL+sjicRna84CvoesKSQVcYiG9P0=";
cargoHash = "sha256-5Zu/Sh9aBMxB+KGC1MHWJAQ8PuE40M6lsenkpFEwJ6A=";
# cargoHash = pkgs.lib.fakeHash;
nativeBuildInputs = [ pkgs.pkg-config ];
buildInputs = [
Expand Down
1 change: 1 addition & 0 deletions garnix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ builds:
- checks.x86_64-linux.*
- include:
- packages.x86_64-linux.default
- devShells.x86_64-linux.default
- checks.x86_64-linux.default
59 changes: 50 additions & 9 deletions src/components/analytics/chart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ const SVG_COORD_X: &str = r#"
dioxus.send((clientX - r.left) / r.width * vb.width);
"#;

/// Canonical metric order: [Weight(0), Reps(1), Distance(2), Duration(3)]
const ALL_METRICS: [Metric; 4] = [
/// Canonical metric order: [Weight(0), Reps(1), Distance(2), Duration(3), Volume(4)]
const ALL_METRICS: [Metric; 5] = [
Metric::Weight,
Metric::Reps,
Metric::Distance,
Metric::Duration,
Metric::Volume,
];

/// Update the cursor timestamp from a client-space X coordinate.
Expand Down Expand Up @@ -62,11 +63,12 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {
let chart2_bottom_margin = 5.0_f64;

// ── Metric availability ───────────────────────────────────────────────────
let metric_has_data: [bool; 4] = ALL_METRICS.map(|m| {
let metric_has_data: [bool; 5] = ALL_METRICS.map(|m| {
data.iter()
.any(|(_, _, dm, pts)| *dm == m && !pts.is_empty())
});
let has_chart2 = metric_has_data[2] || metric_has_data[3];
let has_chart3 = metric_has_data[4];
let has_right_axis = metric_has_data[1] || metric_has_data[3];
let right_pad = if has_right_axis { axis_slot } else { 10.0_f64 };
let left_pad = axis_slot;
Expand All @@ -77,7 +79,15 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {
let chart1_bottom = top_pad + chart_height;
let chart2_top = chart1_bottom + x_gap;
let chart2_bottom = chart2_top + chart_height;
let total_height = if has_chart2 {
let chart3_top = if has_chart2 {
chart2_bottom + x_gap
} else {
chart1_bottom + x_gap
};
let chart3_bottom = chart3_top + chart_height;
let total_height = if has_chart3 {
chart3_bottom + chart2_bottom_margin
} else if has_chart2 {
chart2_bottom + chart2_bottom_margin
} else {
chart1_bottom + 28.0
Expand All @@ -102,7 +112,7 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {

// ── Per-metric Y-axis data ────────────────────────────────────────────────
#[allow(clippy::cast_precision_loss)]
let axis_data: [Option<(&'static str, f64, f64, f64)>; 4] = std::array::from_fn(|i| {
let axis_data: [Option<(&'static str, f64, f64, f64)>; 5] = std::array::from_fn(|i| {
if !metric_has_data[i] {
return None;
}
Expand Down Expand Up @@ -132,8 +142,10 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {
};
let (ct, cb) = if mi < 2 {
(chart1_top, chart1_bottom)
} else {
} else if mi < 4 {
(chart2_top, chart2_bottom)
} else {
(chart3_top, chart3_bottom)
};
let h = cb - ct;
if (max_y - min_y).abs() < f64::EPSILON {
Expand Down Expand Up @@ -181,7 +193,9 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {
Vec::new()
};

let interact_height = if has_chart2 {
let interact_height = if has_chart3 {
chart3_bottom - chart1_top
} else if has_chart2 {
chart2_bottom - chart1_top
} else {
chart_height
Expand Down Expand Up @@ -221,15 +235,29 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {
stroke_width: "1",
}
}
for i in 0..4_usize {
if has_chart3 {
line {
x1: "{left_pad}",
y1: "{chart3_bottom}",
x2: "{left_pad + chart_width}",
y2: "{chart3_bottom}",
stroke: "#555",
stroke_width: "1",
}
}
for i in 0..5_usize {
if let Some((unit, _, min_y, max_y)) = axis_data[i] {
{
// Axis side: odd indices (Reps=1, Duration=3) → right axis;
// even indices (Weight=0, Distance=2, Volume=4) → left axis.
let is_right = i % 2 == 1;
let x_pos = if is_right { left_pad + chart_width } else { left_pad };
let (ct, cb) = if i < 2 {
(chart1_top, chart1_bottom)
} else {
} else if i < 4 {
(chart2_top, chart2_bottom)
} else {
(chart3_top, chart3_bottom)
};
let tick_x1 = if is_right { x_pos } else { x_pos - 4.0 };
let tick_x2 = if is_right { x_pos + 4.0 } else { x_pos };
Expand Down Expand Up @@ -411,6 +439,19 @@ pub fn ChartView(data: SeriesData, colors: Vec<&'static str>) -> Element {
pointer_events: "none",
}
}
if has_chart3 {
line {
x1: "{cx}",
y1: "{chart3_top}",
x2: "{cx}",
y2: "{chart3_bottom}",
stroke: "#fff",
stroke_width: "1",
stroke_opacity: "0.5",
stroke_dasharray: "4 3",
pointer_events: "none",
}
}
}
}
}
Expand Down
Loading
Loading