264 lines
12 KiB
PHP
264 lines
12 KiB
PHP
<?php
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
function statpress_view_activity_page() {
|
|
global $wpdb;
|
|
|
|
$activity_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0;
|
|
|
|
if ( $activity_id === 0 ) {
|
|
echo '<div class="wrap"><h1>Błąd</h1><p>Nie podano ID aktywności.</p></div>';
|
|
return;
|
|
}
|
|
|
|
$table_activities = $wpdb->prefix . 'statpress_activities';
|
|
$table_categories = $wpdb->prefix . 'statpress_categories';
|
|
$table_event_types = $wpdb->prefix . 'statpress_event_types';
|
|
$table_equipment = $wpdb->prefix . 'statpress_equipment';
|
|
|
|
$sql = $wpdb->prepare(
|
|
"
|
|
SELECT a.*, c.name as category_name, c.icon, c.color, et.name as event_type_name, eq.name as equipment_name
|
|
FROM $table_activities a
|
|
LEFT JOIN $table_categories c ON a.category_id = c.id
|
|
LEFT JOIN $table_event_types et ON a.event_type_id = et.id
|
|
LEFT JOIN $table_equipment eq ON a.equipment_id = eq.id
|
|
WHERE a.id = %d
|
|
",
|
|
$activity_id
|
|
);
|
|
|
|
$activity = $wpdb->get_row( $sql );
|
|
|
|
if ( ! $activity ) {
|
|
echo '<div class="wrap"><h1>Błąd</h1><p>Nie znaleziono aktywności o podanym ID.</p></div>';
|
|
return;
|
|
}
|
|
|
|
// Funkcja pomocnicza do wyświetlania wiersza, jeśli wartość istnieje
|
|
$render_row = function( $label, $value, $unit = '', $is_html = false ) {
|
|
if ( ! is_null( $value ) && '' !== $value ) {
|
|
echo '<div class="statpress-single-data-item">';
|
|
echo '<span class="statpress-single-data-label">' . esc_html( $label ) . '</span>';
|
|
echo '<span class="statpress-single-data-value">' . ( $is_html ? wp_kses_post( $value ) : esc_html( $value ) ) . ( $unit ? ' ' . esc_html( $unit ) : '' ) . '</span>';
|
|
echo '</div>';
|
|
}
|
|
};
|
|
|
|
// Prepare map and chart data if GPX exists
|
|
$gpx_data = array();
|
|
$has_gpx_data = false;
|
|
if ( ! empty( $activity->gpx_url ) ) {
|
|
$gpx_data = statpress_parse_gpx_data( $activity->gpx_url );
|
|
$has_gpx_data = ! empty( $gpx_data['points'] );
|
|
}
|
|
|
|
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', array(), '1.9.4', true );
|
|
wp_enqueue_script( 'chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', array(), null, true );
|
|
|
|
wp_register_script( 'statpress-details-loader', false );
|
|
wp_enqueue_script( 'statpress-details-loader' );
|
|
|
|
// Check which profiles have data
|
|
$available_profiles = array();
|
|
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 ) ) );
|
|
|
|
$chart_js = '
|
|
const track_points = ' . json_encode( $gpx_data['points'] ) . ';
|
|
const profiles = ' . json_encode( $gpx_data['profiles'] ) . ';
|
|
let activeChart = null;
|
|
|
|
if (typeof L !== "undefined" && track_points.length > 0) {
|
|
const map = L.map("statpress-activity-map");
|
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: \'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>\' }).addTo(map);
|
|
const polyline = L.polyline(track_points, {color: "' . esc_js( $activity->color ) . '"}).addTo(map);
|
|
map.fitBounds(polyline.getBounds().pad(0.1));
|
|
L.marker(track_points[0]).addTo(map).bindPopup("Start");
|
|
L.marker(track_points[track_points.length - 1]).addTo(map).bindPopup("Koniec");
|
|
}
|
|
|
|
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 chartType = document.querySelector(".statpress-chart-tabs .nav-tab-active").getAttribute("href").substring(1);
|
|
const xAxisType = document.querySelector(\'input[name="statpress_xaxis"]:checked\').value;
|
|
|
|
const yData = profiles[chartType], xData = xAxisConfigs[xAxisType].data;
|
|
const filteredY = [], filteredX = [];
|
|
if(yData) {
|
|
for(let i=0; i<yData.length; i++) {
|
|
if (yData[i] !== null) {
|
|
filteredY.push(yData[i]);
|
|
filteredX.push(xData[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
const ctx = document.getElementById("statpress-details-chart").getContext("2d");
|
|
activeChart = new Chart(ctx, {
|
|
type: "line",
|
|
data: {
|
|
labels: filteredX,
|
|
datasets: [{
|
|
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: xAxisConfigs[xAxisType].label }, ticks: { callback: xAxisType === "time" ? xAxisConfigs.time.formatter : (v) => v, maxRotation: 0, autoSkip: true, maxTicksLimit: 10 } },
|
|
y: { title: { display: true, text: chartConfigs[chartType].unit } }
|
|
},
|
|
plugins: { legend: { display: false } },
|
|
interaction: { intersect: false, mode: "index" },
|
|
}
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll(".statpress-chart-tabs .nav-tab").forEach(t => t.addEventListener("click", e => {
|
|
e.preventDefault();
|
|
document.querySelector(".statpress-chart-tabs .nav-tab-active").classList.remove("nav-tab-active");
|
|
e.target.classList.add("nav-tab-active");
|
|
renderChart();
|
|
}));
|
|
document.querySelectorAll(\'input[name="statpress_xaxis"]\').forEach(r => r.addEventListener("change", renderChart));
|
|
if (document.querySelector(".statpress-chart-tabs .nav-tab")) renderChart();
|
|
';
|
|
wp_add_inline_script( 'statpress-details-loader', 'document.addEventListener("DOMContentLoaded", function() {' . $chart_js . '});' );
|
|
}
|
|
|
|
?>
|
|
<div class="wrap">
|
|
<h1>
|
|
Szczegóły treningu: <?php echo esc_html( $activity->title ); ?>
|
|
<a href="<?php echo esc_url( add_query_arg( array( 'page' => 'statpress-edit-activity', 'id' => $activity->id ), admin_url( 'admin.php' ) ) ); ?>" class="page-title-action">
|
|
Edytuj
|
|
</a>
|
|
</h1>
|
|
|
|
<p><a href="<?php echo esc_url( admin_url( 'admin.php?page=statpress-dashboard' ) ); ?>">← Powrót do listy aktywności</a></p>
|
|
|
|
<div class="postbox" style="margin-top: 20px;">
|
|
<div class="postbox-header"><h2 class="hndle">Podsumowanie</h2></div>
|
|
<div class="inside">
|
|
<h3 style="margin-top: 0; color: #202124;">Główne dane</h3>
|
|
<div class="statpress-single-grid">
|
|
<?php $render_row( 'Kategoria', $activity->category_name ); ?>
|
|
<?php $render_row( 'Data', date_i18n( 'j F Y', strtotime( $activity->date ) ) ); ?>
|
|
<?php $render_row( 'Dystans', number_format( $activity->distance, 2, ',', ' ' ), 'km' ); ?>
|
|
<?php $render_row( 'Czas trwania', $activity->duration ); ?>
|
|
<?php $render_row( 'Spalone kalorie', $activity->calories, 'kcal' ); ?>
|
|
<?php $render_row( 'Typ wydarzenia', $activity->event_type_name ); ?>
|
|
<?php $render_row( 'Sprzęt', $activity->equipment_name ); ?>
|
|
</div>
|
|
<hr>
|
|
<h3 style="color: #202124;">Dane szczegółowe</h3>
|
|
<div class="statpress-single-grid">
|
|
<?php $render_row( 'Średnia prędkość', number_format( $activity->avg_speed, 1, ',', ' ' ), 'km/h' ); ?>
|
|
<?php $render_row( 'Maksymalna prędkość', number_format( $activity->max_speed, 1, ',', ' ' ), 'km/h' ); ?>
|
|
<?php $render_row( 'Średnie tętno', $activity->avg_heart_rate, 'bpm' ); ?>
|
|
<?php $render_row( 'Maksymalne tętno', $activity->max_heart_rate, 'bpm' ); ?>
|
|
<?php $render_row( 'Średni rytm', $activity->avg_cadence, 'rpm' ); ?>
|
|
<?php $render_row( 'Maksymalny rytm', $activity->max_cadence, 'rpm' ); ?>
|
|
<?php $render_row( 'Suma wzniosów', $activity->total_elevation_gain, 'm' ); ?>
|
|
<?php $render_row( 'Suma spadków', $activity->total_elevation_loss, 'm' ); ?>
|
|
<?php $render_row( 'Minimalna wysokość', $activity->min_altitude, 'm n.p.m.' ); ?>
|
|
<?php $render_row( 'Maksymalna wysokość', $activity->max_altitude, 'm n.p.m.' ); ?>
|
|
</div>
|
|
<hr>
|
|
<h3 style="color: #202124;">Notatki i linki</h3>
|
|
<div class="statpress-single-grid">
|
|
<?php $render_row( 'Komentarz', nl2br( esc_html( $activity->comment ) ), '', true ); ?>
|
|
<?php if ( ! empty( $activity->strava_url ) ) : ?>
|
|
<div class="statpress-single-data-item">
|
|
<span class="statpress-single-data-label">Strava</span>
|
|
<span class="statpress-single-data-value"><a href="<?php echo esc_url( $activity->strava_url ); ?>" target="_blank" rel="noopener noreferrer">Zobacz aktywność na Strava</a></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php if ( ! empty( $activity->gpx_url ) ) : ?>
|
|
<div class="statpress-single-data-item">
|
|
<span class="statpress-single-data-label">Plik GPX</span>
|
|
<span class="statpress-single-data-value"><a href="<?php echo esc_url( $activity->gpx_url ); ?>" target="_blank">Pobierz plik GPX</a></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ( $has_gpx_data ) : ?>
|
|
<hr>
|
|
<h3>Mapa Trasy</h3>
|
|
<div id="statpress-activity-map" style="height: 450px; width: 100%; border: 1px solid #ddd; margin-bottom: 20px;"></div>
|
|
|
|
<?php if ( ! empty( $available_profiles ) ) : ?>
|
|
<h3>Wykresy</h3>
|
|
<div class="statpress-charts-container">
|
|
<div class="statpress-chart-controls">
|
|
<nav class="nav-tab-wrapper statpress-chart-tabs">
|
|
<?php
|
|
$is_first = true;
|
|
foreach ( $available_profiles as $key => $label ) :
|
|
?>
|
|
<a href="#<?php echo esc_attr( $key ); ?>" class="nav-tab <?php
|
|
if ( $is_first ) {
|
|
echo 'nav-tab-active';
|
|
$is_first = false; }
|
|
?>
|
|
"><?php echo esc_html( $label ); ?></a>
|
|
<?php endforeach; ?>
|
|
</nav>
|
|
<?php if ( $has_time_data ) : ?>
|
|
<div class="statpress-xaxis-switcher">
|
|
<strong>Oś X:</strong>
|
|
<label><input type="radio" name="statpress_xaxis" value="distance" checked> Dystans</label>
|
|
|
|
<label><input type="radio" name="statpress_xaxis" value="time"> Czas</label>
|
|
</div>
|
|
<?php else : ?>
|
|
<input type="hidden" name="statpress_xaxis" value="distance" checked>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div style="position: relative; height:250px; width:100%;">
|
|
<canvas id="statpress-details-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php elseif ( ! empty( $activity->gpx_url ) ) : ?>
|
|
<hr>
|
|
<div class="notice notice-warning inline">
|
|
<p>Nie udało się wczytać danych z pliku GPX lub plik jest uszkodzony/pusty. Brak danych do wyświetlenia mapy i wykresów.</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|