-
+
+
Wykresy
+
gpx_url ) ) : ?>
-
Mapa Trasy
-
Nie udało się wczytać danych z pliku GPX lub plik jest uszkodzony/pusty.
+
Nie udało się wczytać danych z pliku GPX lub plik jest uszkodzony/pusty. Brak danych do wyświetlenia mapy i wykresów.
@@ -2142,84 +2212,129 @@ function mystat_single_activity_shortcode_handler( $atts ) {
ob_start();
- // Prepare map data if GPX exists
+ // Prepare map and chart data if GPX exists
$gpx_data = [];
+ $has_gpx_data = false;
if ( ! empty( $activity->gpx_url ) ) {
$gpx_data = mystat_parse_gpx_data( $activity->gpx_url );
+ $has_gpx_data = !empty($gpx_data['points']);
+ }
- if ( ! empty( $gpx_data['points'] ) ) {
- // Enqueue scripts for the frontend
- wp_enqueue_style('leaflet-css', 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css');
- wp_enqueue_script('leaflet-js', 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js', [], '1.9.4', true);
- wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);
-
- $map_id = 'mystat-map-' . esc_attr( $activity->id );
- $chart_id = 'mystat-chart-' . esc_attr( $activity->id );
+ $unique_id = 'mystat-activity-' . esc_attr( $activity->id );
- // Pass track data to a script
- wp_register_script('mystat-shortcode-loader-' . $activity->id, false);
- wp_enqueue_script('mystat-shortcode-loader-' . $activity->id);
+ if ($has_gpx_data) {
+ wp_enqueue_style('leaflet-css', 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css');
+ wp_enqueue_script('leaflet-js', 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js', [], '1.9.4', true);
+ wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);
+
+ $map_id = 'map-' . $unique_id;
+ $chart_id = 'chart-' . $unique_id;
+
+ $available_profiles = [];
+ if (!empty(array_filter($gpx_data['profiles']['elevation']))) $available_profiles['elevation'] = 'Wysokość';
+ if (!empty(array_filter($gpx_data['profiles']['speed']))) $available_profiles['speed'] = 'Prędkość';
+ if (!empty(array_filter($gpx_data['profiles']['hr']))) $available_profiles['hr'] = 'Tętno';
+ if (!empty(array_filter($gpx_data['profiles']['cadence']))) $available_profiles['cadence'] = 'Kadencja';
+
+ $has_time_data = !empty(array_filter($gpx_data['profiles']['time'], fn($t) => !is_null($t)));
+
+ wp_register_script('mystat-shortcode-loader-' . $activity->id, false);
+ wp_enqueue_script('mystat-shortcode-loader-' . $activity->id);
+
+ $js_script = '
+ (function() {
+ document.addEventListener("DOMContentLoaded", function() {
+ const uniqueId = "' . esc_js($unique_id) . '";
+ const containerEl = document.getElementById(uniqueId);
+ if (!containerEl || typeof L === "undefined" || typeof Chart === "undefined") return;
- $map_script = '
const trackPoints = ' . json_encode( $gpx_data['points'] ) . ';
+ const profiles = ' . json_encode( $gpx_data['profiles'] ) . ';
+ let activeChart = null;
+
const mapId = "' . esc_js($map_id) . '";
-
- var container = L.DomUtil.get(mapId);
- if(container != null) { container._leaflet_id = null; }
+ const mapEl = document.getElementById(mapId);
+ if (mapEl && trackPoints.length > 0) {
+ if (mapEl._leaflet_id) mapEl._leaflet_id = null;
+ const map = L.map(mapId);
+ L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: \'©
OpenStreetMap\' }).addTo(map);
+ const polyline = L.polyline(trackPoints, {color: "' . esc_js( $activity->category_color ) . '"}).addTo(map);
+ map.fitBounds(polyline.getBounds().pad(0.1));
+ }
- const map = L.map(mapId);
- L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
- attribution: \'©
OpenStreetMap\'
- }).addTo(map);
-
- const polyline = L.polyline(trackPoints, {color: "' . esc_js( $activity->category_color ) . '"}).addTo(map);
- map.fitBounds(polyline.getBounds().pad(0.1));
- ';
+ const chartId = "' . esc_js($chart_id) . '";
+ const chartEl = document.getElementById(chartId);
+ if (!chartEl) return;
- $elevation_chart_script = '';
- if ( ! empty( $gpx_data['elevation_profile'] ) ) {
- $elevation_chart_script = '
- const elevationData = ' . json_encode( $gpx_data['elevation_profile'] ) . ';
- const chartId = "' . esc_js($chart_id) . '";
- const ctx = document.getElementById(chartId).getContext("2d");
- new Chart(ctx, {
+ const chartConfigs = {
+ elevation: { label: "Wysokość", unit: "m n.p.m.", color: "#8e44ad" },
+ speed: { label: "Prędkość", unit: "km/h", color: "#2980b9" },
+ hr: { label: "Tętno", unit: "bpm", color: "#c0392b" },
+ cadence: { label: "Kadencja", unit: "rpm", color: "#27ae60" }
+ };
+ const xAxisConfigs = {
+ distance: { label: "Dystans (km)", data: profiles.distance },
+ time: { label: "Czas", data: profiles.time, formatter: (s) => s === null ? "" : new Date(s * 1000).toISOString().substr(11, 8) }
+ };
+
+ function renderChart() {
+ if (activeChart) activeChart.destroy();
+ const activeTab = containerEl.querySelector(".mystat-chart-tab.active");
+ if (!activeTab) return;
+ const chartType = activeTab.dataset.type;
+ const xAxisRadio = containerEl.querySelector(\'input[name="xaxis-\' + uniqueId + \'"]:checked\');
+ if (!xAxisRadio) return;
+ const xAxisType = xAxisRadio.value;
+
+ const yData = profiles[chartType], xData = xAxisConfigs[xAxisType].data;
+ const filteredY = [], filteredX = [];
+ if(yData) {
+ for(let i=0; i
p.distance),
+ labels: filteredX,
datasets: [{
- label: "Wysokość (m)",
- data: elevationData.map(p => p.elevation),
- borderColor: "' . esc_js( $activity->category_color ) . '",
- backgroundColor: "' . esc_js( $activity->category_color ) . '20",
+ label: chartConfigs[chartType].label, data: filteredY,
+ borderColor: chartConfigs[chartType].color, backgroundColor: chartConfigs[chartType].color + "20",
fill: true, pointRadius: 0, tension: 0.1
}]
},
options: {
responsive: true, maintainAspectRatio: false,
scales: {
- x: { title: { display: true, text: "Dystans (km)" } },
- y: { title: { display: true, text: "Wysokość (m n.p.m.)" } }
+ x: { title: { display: true, text: xAxisConfigs[xAxisType].label }, ticks: { callback: xAxisType === "time" ? xAxisConfigs.time.formatter : (v) => v, maxRotation: 0, autoSkip: true, maxTicksLimit: 7 } },
+ y: { title: { display: true, text: chartConfigs[chartType].unit } }
},
- plugins: { legend: { display: false } }
+ plugins: { legend: { display: false } },
+ interaction: { intersect: false, mode: "index" },
}
});
- ';
- }
+ }
- wp_add_inline_script('mystat-shortcode-loader-' . $activity->id,
- '(function() {
- document.addEventListener("DOMContentLoaded", function() {
- if (typeof L === "undefined" || typeof Chart === "undefined") return;
- ' . $map_script . '
- ' . $elevation_chart_script . '
- });
- })();'
- );
- }
+ containerEl.querySelectorAll(".mystat-chart-tab").forEach(t => t.addEventListener("click", e => {
+ e.preventDefault();
+ containerEl.querySelector(".mystat-chart-tab.active").classList.remove("active");
+ e.currentTarget.classList.add("active");
+ renderChart();
+ }));
+ containerEl.querySelectorAll(\'input[name="xaxis-\' + uniqueId + \'"]\').forEach(r => r.addEventListener("change", renderChart));
+ if (containerEl.querySelector(".mystat-chart-tab")) renderChart();
+ });
+ })();';
+ wp_add_inline_script('mystat-shortcode-loader-' . $activity->id, $js_script);
}
?>
-
+
title ); ?>
date ) ) ); ?>
@@ -2247,14 +2362,35 @@ function mystat_single_activity_shortcode_handler( $atts ) {
-
-
-
+
+
-
-
-
-
+
+
+
+
+ $label ) : ?>
+
+
+
+
+
+ Oś X:
+
+
+
+
+
+
+
+
+
+
+
+
+