Better charts
This commit is contained in:
+273
-71
@@ -432,13 +432,15 @@ function mystat_yearly_summary_page() {
|
|||||||
MONTH(date) as month_num,
|
MONTH(date) as month_num,
|
||||||
SUM(distance) as total_distance,
|
SUM(distance) as total_distance,
|
||||||
SUM(calories) as total_calories,
|
SUM(calories) as total_calories,
|
||||||
SEC_TO_TIME(SUM(TIME_TO_SEC(duration))) as total_duration
|
SUM(TIME_TO_SEC(duration)) as total_seconds,
|
||||||
|
COUNT(id) as activity_count
|
||||||
FROM $table_activities
|
FROM $table_activities
|
||||||
WHERE YEAR(date) = %d
|
WHERE YEAR(date) = %d
|
||||||
GROUP BY month_num
|
GROUP BY month_num
|
||||||
ORDER BY month_num ASC
|
ORDER BY month_num ASC
|
||||||
", $current_year);
|
", $current_year);
|
||||||
|
|
||||||
|
|
||||||
$monthly_summary = $wpdb->get_results( $sql, OBJECT_K ); // OBJECT_K zwróci tablicę z kluczami będącymi numerami miesięcy
|
$monthly_summary = $wpdb->get_results( $sql, OBJECT_K ); // OBJECT_K zwróci tablicę z kluczami będącymi numerami miesięcy
|
||||||
|
|
||||||
// Przygotowanie danych dla wszystkich 12 miesięcy
|
// Przygotowanie danych dla wszystkich 12 miesięcy
|
||||||
@@ -468,16 +470,14 @@ function mystat_yearly_summary_page() {
|
|||||||
$full_year_summary[$i] = (object) [
|
$full_year_summary[$i] = (object) [
|
||||||
'month_name' => $month_name,
|
'month_name' => $month_name,
|
||||||
'total_distance' => $data ? $data->total_distance : 0,
|
'total_distance' => $data ? $data->total_distance : 0,
|
||||||
'total_calories' => $data ? $data->total_calories : 0,
|
'total_calories' => $data ? (int)$data->total_calories : 0,
|
||||||
'total_duration' => $data ? $data->total_duration : '00:00:00',
|
'total_seconds' => $data ? (int)$data->total_seconds : 0,
|
||||||
|
'activity_count' => $data ? (int)$data->activity_count : 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
$total_year_distance += $full_year_summary[$i]->total_distance;
|
$total_year_distance += $full_year_summary[$i]->total_distance;
|
||||||
|
$total_year_seconds += $full_year_summary[$i]->total_seconds;
|
||||||
$total_year_calories += $full_year_summary[$i]->total_calories;
|
$total_year_calories += $full_year_summary[$i]->total_calories;
|
||||||
if ( $data && ! empty( $data->total_duration ) ) {
|
|
||||||
list($h, $m, $s) = explode(':', $data->total_duration);
|
|
||||||
$total_year_seconds += $h * 3600 + $m * 60 + $s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$total_year_hours = floor($total_year_seconds / 3600);
|
$total_year_hours = floor($total_year_seconds / 3600);
|
||||||
@@ -485,44 +485,105 @@ function mystat_yearly_summary_page() {
|
|||||||
$total_year_duration_formatted = sprintf('%d godz. %d min.', $total_year_hours, $total_year_minutes);
|
$total_year_duration_formatted = sprintf('%d godz. %d min.', $total_year_hours, $total_year_minutes);
|
||||||
|
|
||||||
// Przygotowanie danych dla wykresu
|
// Przygotowanie danych dla wykresu
|
||||||
$chart_labels = [];
|
$chart_labels_js = [];
|
||||||
$chart_data_distance = [];
|
$chart_datasets = [
|
||||||
|
'distance' => [],
|
||||||
|
'duration' => [],
|
||||||
|
'calories' => [],
|
||||||
|
'activities' => [],
|
||||||
|
];
|
||||||
|
|
||||||
foreach ($full_year_summary as $month_data) {
|
foreach ($full_year_summary as $month_data) {
|
||||||
$chart_labels[] = $month_data->month_name;
|
$chart_labels_js[] = $month_data->month_name;
|
||||||
$chart_data_distance[] = round((float)$month_data->total_distance, 2);
|
$chart_datasets['distance'][] = round((float)$month_data->total_distance, 2);
|
||||||
|
$chart_datasets['duration'][] = round($month_data->total_seconds / 3600, 2); // w godzinach
|
||||||
|
$chart_datasets['calories'][] = $month_data->total_calories;
|
||||||
|
$chart_datasets['activities'][] = $month_data->activity_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Włączenie skryptów dla Chart.js
|
// Włączenie skryptów dla Chart.js
|
||||||
wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);
|
wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);
|
||||||
wp_register_script('mystat-chart-loader', false);
|
wp_register_script('mystat-chart-loader', false);
|
||||||
wp_enqueue_script('mystat-chart-loader');
|
wp_enqueue_script('mystat-chart-loader');
|
||||||
|
|
||||||
|
$chart_configs = [
|
||||||
|
'distance' => [
|
||||||
|
'label' => 'Dystans (km)',
|
||||||
|
'data' => $chart_datasets['distance'],
|
||||||
|
'backgroundColor' => 'rgba(52, 152, 219, 0.5)',
|
||||||
|
'borderColor' => 'rgba(52, 152, 219, 1)',
|
||||||
|
'yAxisLabel' => 'Kilometry'
|
||||||
|
],
|
||||||
|
'duration' => [
|
||||||
|
'label' => 'Czas trwania (godz.)',
|
||||||
|
'data' => $chart_datasets['duration'],
|
||||||
|
'backgroundColor' => 'rgba(26, 188, 156, 0.5)',
|
||||||
|
'borderColor' => 'rgba(26, 188, 156, 1)',
|
||||||
|
'yAxisLabel' => 'Godziny'
|
||||||
|
],
|
||||||
|
'calories' => [
|
||||||
|
'label' => 'Kalorie (kcal)',
|
||||||
|
'data' => $chart_datasets['calories'],
|
||||||
|
'backgroundColor' => 'rgba(231, 76, 60, 0.5)',
|
||||||
|
'borderColor' => 'rgba(231, 76, 60, 1)',
|
||||||
|
'yAxisLabel' => 'kcal'
|
||||||
|
],
|
||||||
|
'activities' => [
|
||||||
|
'label' => 'Liczba aktywności',
|
||||||
|
'data' => $chart_datasets['activities'],
|
||||||
|
'backgroundColor' => 'rgba(241, 196, 15, 0.5)',
|
||||||
|
'borderColor' => 'rgba(241, 196, 15, 1)',
|
||||||
|
'yAxisLabel' => 'Ilość'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
wp_add_inline_script('mystat-chart-loader', '
|
wp_add_inline_script('mystat-chart-loader', '
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const ctx = document.getElementById("mystatYearlyChart");
|
const chartLabels = ' . json_encode($chart_labels_js) . ';
|
||||||
if (!ctx) return;
|
const chartConfigs = ' . json_encode($chart_configs) . ';
|
||||||
new Chart(ctx, {
|
let activeChart = null;
|
||||||
|
|
||||||
|
const tabs = document.querySelectorAll(".nav-tab");
|
||||||
|
tabs.forEach(tab => {
|
||||||
|
tab.addEventListener("click", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
tabs.forEach(t => t.classList.remove("nav-tab-active"));
|
||||||
|
this.classList.add("nav-tab-active");
|
||||||
|
|
||||||
|
const chartType = this.getAttribute("href").substring(1);
|
||||||
|
renderChart(chartType);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderChart(type) {
|
||||||
|
if (activeChart) {
|
||||||
|
activeChart.destroy();
|
||||||
|
}
|
||||||
|
const config = chartConfigs[type];
|
||||||
|
const ctx = document.getElementById("mystatYearlyChart").getContext("2d");
|
||||||
|
activeChart = new Chart(ctx, {
|
||||||
type: "bar",
|
type: "bar",
|
||||||
data: {
|
data: {
|
||||||
labels: ' . json_encode($chart_labels) . ',
|
labels: chartLabels,
|
||||||
datasets: [{
|
datasets: [{
|
||||||
label: "Dystans (km)",
|
label: config.label,
|
||||||
data: ' . json_encode($chart_data_distance) . ',
|
data: config.data,
|
||||||
backgroundColor: "rgba(52, 152, 219, 0.5)",
|
backgroundColor: config.backgroundColor,
|
||||||
borderColor: "rgba(52, 152, 219, 1)",
|
borderColor: config.borderColor,
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true, maintainAspectRatio: false,
|
||||||
maintainAspectRatio: false,
|
scales: { y: { beginAtZero: true, title: { display: true, text: config.yAxisLabel } } }
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
title: { display: true, text: "Kilometry" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render initial chart
|
||||||
|
if (tabs.length > 0) {
|
||||||
|
renderChart(tabs[0].getAttribute("href").substring(1));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
');
|
');
|
||||||
|
|
||||||
@@ -546,8 +607,14 @@ function mystat_yearly_summary_page() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="postbox" style="margin-bottom: 20px;">
|
<div class="postbox" style="margin-bottom: 20px;">
|
||||||
<div class="postbox-header"><h2 class="hndle">Wykres Dystansu w <?php echo esc_html($current_year); ?></h2></div>
|
<div class="postbox-header"><h2 class="hndle">Wykresy dla <?php echo esc_html($current_year); ?></h2></div>
|
||||||
<div class="inside">
|
<div class="inside">
|
||||||
|
<nav class="nav-tab-wrapper" style="margin-bottom: 20px;">
|
||||||
|
<a href="#distance" class="nav-tab nav-tab-active">Dystans</a>
|
||||||
|
<a href="#duration" class="nav-tab">Czas</a>
|
||||||
|
<a href="#calories" class="nav-tab">Kalorie</a>
|
||||||
|
<a href="#activities" class="nav-tab">Aktywności</a>
|
||||||
|
</nav>
|
||||||
<div style="position: relative; height:40vh; width:100%;">
|
<div style="position: relative; height:40vh; width:100%;">
|
||||||
<canvas id="mystatYearlyChart"></canvas>
|
<canvas id="mystatYearlyChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
@@ -564,7 +631,7 @@ function mystat_yearly_summary_page() {
|
|||||||
<td><?php echo esc_html( $month_data->month_name ); ?></td>
|
<td><?php echo esc_html( $month_data->month_name ); ?></td>
|
||||||
<td><?php echo number_format( $month_data->total_distance, 2, ',', ' ' ); ?></td>
|
<td><?php echo number_format( $month_data->total_distance, 2, ',', ' ' ); ?></td>
|
||||||
<td><?php echo number_format( $month_data->total_calories, 0, ',', ' ' ); ?></td>
|
<td><?php echo number_format( $month_data->total_calories, 0, ',', ' ' ); ?></td>
|
||||||
<td><?php echo esc_html( $month_data->total_duration ); ?></td>
|
<td><?php echo esc_html( gmdate('H:i:s', $month_data->total_seconds) ); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<tr class="alternate">
|
<tr class="alternate">
|
||||||
@@ -580,12 +647,12 @@ function mystat_yearly_summary_page() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches and parses a GPX file from a URL to extract track points.
|
* Fetches and parses a GPX file from a URL to extract track points and elevation profile.
|
||||||
*
|
*
|
||||||
* @param string $gpx_url The URL of the GPX file.
|
* @param string $gpx_url The URL of the GPX file.
|
||||||
* @return array An array of [lat, lon] coordinates, or an empty array on failure.
|
* @return array An array containing 'points' for the map and 'elevation_profile'.
|
||||||
*/
|
*/
|
||||||
function mystat_get_track_from_gpx_url( $gpx_url ) {
|
function mystat_parse_gpx_data( $gpx_url ) {
|
||||||
if ( empty( $gpx_url ) ) {
|
if ( empty( $gpx_url ) ) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -609,18 +676,68 @@ function mystat_get_track_from_gpx_url( $gpx_url ) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$points = [];
|
$track_data = [
|
||||||
|
'points' => [],
|
||||||
|
'elevation_profile' => [],
|
||||||
|
];
|
||||||
|
$raw_points = [];
|
||||||
|
|
||||||
|
// Extract raw points with lat, lon, ele
|
||||||
if ( isset( $gpx->trk ) ) {
|
if ( isset( $gpx->trk ) ) {
|
||||||
foreach ( $gpx->trk->trkseg as $trkseg ) {
|
foreach ( $gpx->trk->trkseg as $trkseg ) {
|
||||||
foreach ( $trkseg->trkpt as $trkpt ) {
|
foreach ( $trkseg->trkpt as $trkpt ) {
|
||||||
if ( isset( $trkpt['lat'] ) && isset( $trkpt['lon'] ) ) {
|
if ( isset( $trkpt['lat'], $trkpt['lon'] ) ) {
|
||||||
$points[] = [ (float) $trkpt['lat'], (float) $trkpt['lon'] ];
|
$raw_points[] = [
|
||||||
|
'lat' => (float) $trkpt['lat'],
|
||||||
|
'lon' => (float) $trkpt['lon'],
|
||||||
|
'ele' => isset( $trkpt->ele ) ? (float) $trkpt->ele : null,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $points;
|
if ( empty( $raw_points ) ) {
|
||||||
|
return $track_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process raw points to calculate profile
|
||||||
|
$cumulative_distance = 0;
|
||||||
|
$elevation_profile = [];
|
||||||
|
$map_points = [];
|
||||||
|
|
||||||
|
$haversine = function( $lat1, $lon1, $lat2, $lon2 ) {
|
||||||
|
$earth_radius = 6371; // in km
|
||||||
|
$dLat = deg2rad( $lat2 - $lat1 );
|
||||||
|
$dLon = deg2rad( $lon2 - $lon1 );
|
||||||
|
$a = sin( $dLat / 2 ) * sin( $dLat / 2 ) +
|
||||||
|
cos( deg2rad( $lat1 ) ) * cos( deg2rad( $lat2 ) ) *
|
||||||
|
sin( $dLon / 2 ) * sin( $dLon / 2 );
|
||||||
|
$c = 2 * atan2( sqrt( $a ), sqrt( 1 - $a ) );
|
||||||
|
return $earth_radius * $c;
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach ( $raw_points as $i => $point ) {
|
||||||
|
$map_points[] = [ $point['lat'], $point['lon'] ];
|
||||||
|
|
||||||
|
if ( $i > 0 ) {
|
||||||
|
$prev_point = $raw_points[ $i - 1 ];
|
||||||
|
$distance_increment = $haversine( $prev_point['lat'], $prev_point['lon'], $point['lat'], $point['lon'] );
|
||||||
|
$cumulative_distance += $distance_increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! is_null( $point['ele'] ) ) {
|
||||||
|
$elevation_profile[] = [
|
||||||
|
'distance' => round( $cumulative_distance, 3 ), // in km
|
||||||
|
'elevation' => round( $point['ele'], 2 ), // in m
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$track_data['points'] = $map_points;
|
||||||
|
$track_data['elevation_profile'] = $elevation_profile;
|
||||||
|
|
||||||
|
return $track_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mystat_infographic_page() {
|
function mystat_infographic_page() {
|
||||||
@@ -1123,35 +1240,68 @@ function mystat_view_activity_page() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prepare map data if GPX exists
|
// Prepare map and chart data if GPX exists
|
||||||
$track_points = [];
|
$gpx_data = [];
|
||||||
if ( ! empty( $activity->gpx_url ) ) {
|
if ( ! empty( $activity->gpx_url ) ) {
|
||||||
// Note: For performance, you might want to cache the parsed points in post meta
|
$gpx_data = mystat_parse_gpx_data( $activity->gpx_url );
|
||||||
// rather than parsing the file on every page load.
|
|
||||||
$track_points = mystat_get_track_from_gpx_url( $activity->gpx_url );
|
|
||||||
|
|
||||||
if ( ! empty( $track_points ) ) {
|
if ( ! empty( $gpx_data['points'] ) ) {
|
||||||
// Enqueue Leaflet assets. For simplicity, this is done here.
|
|
||||||
// A better approach is to use the 'admin_enqueue_scripts' hook.
|
|
||||||
wp_enqueue_style('leaflet-css', 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css');
|
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('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);
|
||||||
|
|
||||||
// Pass track data to a script
|
wp_register_script('mystat-details-loader', false);
|
||||||
wp_register_script('mystat-map-loader', false);
|
wp_enqueue_script('mystat-details-loader');
|
||||||
wp_enqueue_script('mystat-map-loader');
|
|
||||||
wp_add_inline_script('mystat-map-loader',
|
$map_script = '
|
||||||
'const mystat_track_points = ' . json_encode($track_points) . ';' .
|
const track_points = ' . json_encode($gpx_data['points']) . ';
|
||||||
'document.addEventListener("DOMContentLoaded", function() {
|
if (typeof L !== "undefined" && track_points.length > 0) {
|
||||||
if (typeof L === "undefined" || typeof mystat_track_points === "undefined" || mystat_track_points.length === 0) return;
|
|
||||||
const map = L.map("mystat-activity-map");
|
const map = L.map("mystat-activity-map");
|
||||||
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
attribution: \'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors\'
|
attribution: \'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors\'
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
const polyline = L.polyline(mystat_track_points, {color: "#' . esc_js( ltrim($activity->color, '#') ) . '"}).addTo(map);
|
const polyline = L.polyline(track_points, {color: "' . esc_js( $activity->color ) . '"}).addTo(map);
|
||||||
map.fitBounds(polyline.getBounds().pad(0.1));
|
map.fitBounds(polyline.getBounds().pad(0.1));
|
||||||
L.marker(mystat_track_points[0]).addTo(map).bindPopup("Start");
|
L.marker(track_points[0]).addTo(map).bindPopup("Start");
|
||||||
L.marker(mystat_track_points[mystat_track_points.length - 1]).addTo(map).bindPopup("Koniec");
|
L.marker(track_points[track_points.length - 1]).addTo(map).bindPopup("Koniec");
|
||||||
});'
|
}
|
||||||
|
';
|
||||||
|
|
||||||
|
$elevation_chart_script = '';
|
||||||
|
if ( ! empty( $gpx_data['elevation_profile'] ) ) {
|
||||||
|
$elevation_chart_script = '
|
||||||
|
const elevation_data = ' . json_encode( $gpx_data['elevation_profile'] ) . ';
|
||||||
|
if (typeof Chart !== "undefined" && elevation_data.length > 0) {
|
||||||
|
const ctx = document.getElementById("mystat-elevation-chart").getContext("2d");
|
||||||
|
new Chart(ctx, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: elevation_data.map(p => p.distance),
|
||||||
|
datasets: [{
|
||||||
|
label: "Wysokość (m)",
|
||||||
|
data: elevation_data.map(p => p.elevation),
|
||||||
|
borderColor: "' . esc_js( $activity->color ) . '",
|
||||||
|
backgroundColor: "' . esc_js( $activity->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.)" } }
|
||||||
|
},
|
||||||
|
plugins: { legend: { display: false } }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_add_inline_script('mystat-details-loader',
|
||||||
|
'document.addEventListener("DOMContentLoaded", function() {' . $map_script . $elevation_chart_script . '});'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1211,10 +1361,18 @@ function mystat_view_activity_page() {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<?php if ( ! empty( $track_points ) ) : ?>
|
<?php if ( ! empty( $gpx_data['points'] ) ) : ?>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Mapa Trasy</h3>
|
<h3>Mapa Trasy</h3>
|
||||||
<div id="mystat-activity-map" style="height: 450px; width: 100%; border: 1px solid #ddd;"></div>
|
<div id="mystat-activity-map" style="height: 450px; width: 100%; border: 1px solid #ddd; margin-bottom: 20px;"></div>
|
||||||
|
|
||||||
|
<?php if ( ! empty( $gpx_data['elevation_profile'] ) ) : ?>
|
||||||
|
<h3>Profil Wysokości</h3>
|
||||||
|
<div style="position: relative; height:250px; width:100%;">
|
||||||
|
<canvas id="mystat-elevation-chart"></canvas>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php elseif ( ! empty( $activity->gpx_url ) ) : ?>
|
<?php elseif ( ! empty( $activity->gpx_url ) ) : ?>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Mapa Trasy</h3>
|
<h3>Mapa Trasy</h3>
|
||||||
@@ -1790,7 +1948,7 @@ function mystat_single_activity_shortcode_handler( $atts ) {
|
|||||||
// Pobieranie danych z bazy
|
// Pobieranie danych z bazy
|
||||||
$table_activities = $wpdb->prefix . 'mystat_activities';
|
$table_activities = $wpdb->prefix . 'mystat_activities';
|
||||||
$sql = $wpdb->prepare("
|
$sql = $wpdb->prepare("
|
||||||
SELECT a.*, c.name as category_name, et.name as event_type_name, eq.name as equipment_name
|
SELECT a.*, c.name as category_name, c.color as category_color, et.name as event_type_name, eq.name as equipment_name
|
||||||
FROM $table_activities a
|
FROM $table_activities a
|
||||||
LEFT JOIN {$wpdb->prefix}mystat_categories c ON a.category_id = c.id
|
LEFT JOIN {$wpdb->prefix}mystat_categories c ON a.category_id = c.id
|
||||||
LEFT JOIN {$wpdb->prefix}mystat_event_types et ON a.event_type_id = et.id
|
LEFT JOIN {$wpdb->prefix}mystat_event_types et ON a.event_type_id = et.id
|
||||||
@@ -1817,25 +1975,25 @@ function mystat_single_activity_shortcode_handler( $atts ) {
|
|||||||
ob_start();
|
ob_start();
|
||||||
|
|
||||||
// Prepare map data if GPX exists
|
// Prepare map data if GPX exists
|
||||||
$track_points = [];
|
$gpx_data = [];
|
||||||
if ( ! empty( $activity->gpx_url ) ) {
|
if ( ! empty( $activity->gpx_url ) ) {
|
||||||
$track_points = mystat_get_track_from_gpx_url( $activity->gpx_url );
|
$gpx_data = mystat_parse_gpx_data( $activity->gpx_url );
|
||||||
|
|
||||||
if ( ! empty( $track_points ) ) {
|
if ( ! empty( $gpx_data['points'] ) ) {
|
||||||
// Enqueue scripts for the frontend
|
// Enqueue scripts for the frontend
|
||||||
wp_enqueue_style('leaflet-css', 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css');
|
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('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 );
|
$map_id = 'mystat-map-' . esc_attr( $activity->id );
|
||||||
|
$chart_id = 'mystat-chart-' . esc_attr( $activity->id );
|
||||||
|
|
||||||
// Pass track data to a script
|
// Pass track data to a script
|
||||||
wp_register_script('mystat-shortcode-map-loader-' . $activity->id, false);
|
wp_register_script('mystat-shortcode-loader-' . $activity->id, false);
|
||||||
wp_enqueue_script('mystat-shortcode-map-loader-' . $activity->id);
|
wp_enqueue_script('mystat-shortcode-loader-' . $activity->id);
|
||||||
wp_add_inline_script('mystat-shortcode-map-loader-' . $activity->id,
|
|
||||||
'(function() {
|
$map_script = '
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
const trackPoints = ' . json_encode( $gpx_data['points'] ) . ';
|
||||||
if (typeof L === "undefined") return;
|
|
||||||
const trackPoints = ' . json_encode( $track_points ) . ';
|
|
||||||
const mapId = "' . esc_js($map_id) . '";
|
const mapId = "' . esc_js($map_id) . '";
|
||||||
|
|
||||||
var container = L.DomUtil.get(mapId);
|
var container = L.DomUtil.get(mapId);
|
||||||
@@ -1846,8 +2004,46 @@ function mystat_single_activity_shortcode_handler( $atts ) {
|
|||||||
attribution: \'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>\'
|
attribution: \'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>\'
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
const polyline = L.polyline(trackPoints, {color: "#3498db"}).addTo(map);
|
const polyline = L.polyline(trackPoints, {color: "' . esc_js( $activity->category_color ) . '"}).addTo(map);
|
||||||
map.fitBounds(polyline.getBounds().pad(0.1));
|
map.fitBounds(polyline.getBounds().pad(0.1));
|
||||||
|
';
|
||||||
|
|
||||||
|
$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, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: elevationData.map(p => p.distance),
|
||||||
|
datasets: [{
|
||||||
|
label: "Wysokość (m)",
|
||||||
|
data: elevationData.map(p => p.elevation),
|
||||||
|
borderColor: "' . esc_js( $activity->category_color ) . '",
|
||||||
|
backgroundColor: "' . esc_js( $activity->category_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.)" } }
|
||||||
|
},
|
||||||
|
plugins: { legend: { display: false } }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
|
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 . '
|
||||||
});
|
});
|
||||||
})();'
|
})();'
|
||||||
);
|
);
|
||||||
@@ -1883,8 +2079,14 @@ function mystat_single_activity_shortcode_handler( $atts ) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ( ! empty( $track_points ) ) : ?>
|
<?php if ( ! empty( $gpx_data['points'] ) ) : ?>
|
||||||
<div id="<?php echo $map_id; ?>" style="height: 350px; width: 100%; margin-top: 15px; border-radius: 5px;"></div>
|
<div id="<?php echo $map_id; ?>" style="height: 350px; width: 100%; margin-top: 15px; border-radius: 5px; margin-bottom: 20px;"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( ! empty( $gpx_data['elevation_profile'] ) ) : ?>
|
||||||
|
<div style="position: relative; height:250px; width:100%;">
|
||||||
|
<canvas id="<?php echo $chart_id; ?>"></canvas>
|
||||||
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
Reference in New Issue
Block a user