292 lines
12 KiB
PHP
292 lines
12 KiB
PHP
<?php
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
function mystat_yearly_summary_page() {
|
|
global $wpdb;
|
|
$table_activities = $wpdb->prefix . 'mystat_activities';
|
|
|
|
$current_year = isset( $_GET['year'] ) ? intval( $_GET['year'] ) : current_time( 'Y' );
|
|
|
|
// Pobierz dostępne lata z bazy danych
|
|
$available_years = $wpdb->get_col( "SELECT DISTINCT YEAR(date) FROM $table_activities ORDER BY YEAR(date) DESC" );
|
|
if ( empty( $available_years ) ) {
|
|
$available_years = array( current_time( 'Y' ) ); // Domyślny rok, jeśli brak danych
|
|
}
|
|
|
|
// --- GOALS SECTION ---
|
|
$table_goals = $wpdb->prefix . 'mystat_goals';
|
|
$goals_for_year = $wpdb->get_results(
|
|
$wpdb->prepare(
|
|
"SELECT * FROM {$table_goals} WHERE year = %d ORDER BY name ASC",
|
|
$current_year
|
|
)
|
|
);
|
|
|
|
// Zapytanie SQL do grupowania danych miesięcznie
|
|
$sql = $wpdb->prepare(
|
|
"
|
|
SELECT
|
|
MONTH(date) as month_num,
|
|
SUM(distance) as total_distance,
|
|
SUM(calories) as total_calories,
|
|
SUM(TIME_TO_SEC(duration)) as total_seconds,
|
|
COUNT(id) as activity_count
|
|
FROM $table_activities
|
|
WHERE YEAR(date) = %d
|
|
GROUP BY month_num
|
|
ORDER BY month_num ASC
|
|
",
|
|
$current_year
|
|
);
|
|
|
|
$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
|
|
$full_year_summary = array();
|
|
$total_year_distance = 0;
|
|
$total_year_calories = 0;
|
|
$total_year_seconds = 0;
|
|
|
|
// Określ, ile miesięcy pokazać, aby uniknąć zer dla przyszłych miesięcy
|
|
$this_year = (int) current_time( 'Y' );
|
|
$this_month = (int) current_time( 'n' );
|
|
$loop_until_month = 12; // Domyślnie dla lat ubiegłych
|
|
|
|
if ( $current_year === $this_year ) {
|
|
// Dla bieżącego roku, pokaż miesiące do bieżącego miesiąca
|
|
$loop_until_month = $this_month;
|
|
} elseif ( $current_year > $this_year ) {
|
|
// Dla przyszłych lat, pokaż miesiące tylko do ostatniego, w którym są dane
|
|
$last_month_with_data = $wpdb->get_var( $wpdb->prepare( "SELECT MAX(MONTH(date)) FROM $table_activities WHERE YEAR(date) = %d", $current_year ) );
|
|
$loop_until_month = $last_month_with_data ? (int) $last_month_with_data : 0;
|
|
}
|
|
|
|
for ( $i = 1; $i <= $loop_until_month; $i++ ) {
|
|
$month_name = date_i18n( 'F', mktime( 0, 0, 0, $i, 10 ) ); // Nazwa miesiąca
|
|
$data = isset( $monthly_summary[ $i ] ) ? $monthly_summary[ $i ] : null;
|
|
|
|
$full_year_summary[ $i ] = (object) array(
|
|
'month_name' => $month_name,
|
|
'total_distance' => $data ? $data->total_distance : 0,
|
|
'total_calories' => $data ? (int) $data->total_calories : 0,
|
|
'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_seconds += $full_year_summary[ $i ]->total_seconds;
|
|
$total_year_calories += $full_year_summary[ $i ]->total_calories;
|
|
}
|
|
|
|
$total_year_hours = floor( $total_year_seconds / 3600 );
|
|
$total_year_minutes = floor( ( $total_year_seconds % 3600 ) / 60 );
|
|
$total_year_duration_formatted = sprintf( '%d godz. %d min.', $total_year_hours, $total_year_minutes );
|
|
|
|
// Przygotowanie danych dla wykresu
|
|
$chart_labels_js = array();
|
|
$chart_datasets = array(
|
|
'distance' => array(),
|
|
'duration' => array(),
|
|
'calories' => array(),
|
|
'activities' => array(),
|
|
);
|
|
|
|
foreach ( $full_year_summary as $month_data ) {
|
|
$chart_labels_js[] = $month_data->month_name;
|
|
$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
|
|
wp_enqueue_script( 'chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', array(), null, true );
|
|
wp_register_script( 'mystat-chart-loader', false );
|
|
wp_enqueue_script( 'mystat-chart-loader' );
|
|
|
|
$chart_configs = array(
|
|
'distance' => array(
|
|
'label' => 'Dystans (km)',
|
|
'data' => $chart_datasets['distance'],
|
|
'backgroundColor' => 'rgba(52, 152, 219, 0.5)',
|
|
'borderColor' => 'rgba(52, 152, 219, 1)',
|
|
'yAxisLabel' => 'Kilometry',
|
|
),
|
|
'duration' => array(
|
|
'label' => 'Czas trwania (godz.)',
|
|
'data' => $chart_datasets['duration'],
|
|
'backgroundColor' => 'rgba(26, 188, 156, 0.5)',
|
|
'borderColor' => 'rgba(26, 188, 156, 1)',
|
|
'yAxisLabel' => 'Godziny',
|
|
),
|
|
'calories' => array(
|
|
'label' => 'Kalorie (kcal)',
|
|
'data' => $chart_datasets['calories'],
|
|
'backgroundColor' => 'rgba(231, 76, 60, 0.5)',
|
|
'borderColor' => 'rgba(231, 76, 60, 1)',
|
|
'yAxisLabel' => 'kcal',
|
|
),
|
|
'activities' => array(
|
|
'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',
|
|
'
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const chartLabels = ' . json_encode( $chart_labels_js ) . ';
|
|
const chartConfigs = ' . json_encode( $chart_configs ) . ';
|
|
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",
|
|
data: {
|
|
labels: chartLabels,
|
|
datasets: [{
|
|
label: config.label,
|
|
data: config.data,
|
|
backgroundColor: config.backgroundColor,
|
|
borderColor: config.borderColor,
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true, maintainAspectRatio: false,
|
|
scales: { y: { beginAtZero: true, title: { display: true, text: config.yAxisLabel } } }
|
|
}
|
|
});
|
|
}
|
|
|
|
// Render initial chart
|
|
if (tabs.length > 0) {
|
|
renderChart(tabs[0].getAttribute("href").substring(1));
|
|
}
|
|
});
|
|
'
|
|
);
|
|
|
|
?>
|
|
<div class="wrap">
|
|
<h1>Podsumowanie Roczne</h1>
|
|
|
|
<div class="tablenav top">
|
|
<div class="alignleft actions">
|
|
<label for="filter-by-year" class="screen-reader-text">Filtruj według roku</label>
|
|
<form method="get" style="display: flex; gap: 5px; align-items: center;">
|
|
<input type="hidden" name="page" value="mystat-yearly-summary">
|
|
<select name="year" id="filter-by-year">
|
|
<?php foreach ( $available_years as $year_option ) : ?>
|
|
<option value="<?php echo esc_attr( $year_option ); ?>" <?php selected( $current_year, $year_option ); ?>><?php echo esc_html( $year_option ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php submit_button( 'Filtruj', 'secondary', 'filter_action', false ); ?>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ( ! empty( $goals_for_year ) ) : ?>
|
|
<div class="postbox" style="margin-bottom: 20px;">
|
|
<div class="postbox-header"><h2 class="hndle">Cele na <?php echo esc_html( $current_year ); ?></h2></div>
|
|
<div class="inside">
|
|
<ul class="mystat-goals-list">
|
|
<?php
|
|
foreach ( $goals_for_year as $goal ) :
|
|
$progress = mystat_get_goal_progress( $goal );
|
|
$percentage = min( 100, $progress['percentage'] );
|
|
|
|
$target_formatted = '';
|
|
$current_formatted = '';
|
|
if ( 'duration_sec' === $goal->goal_type ) {
|
|
$target_formatted = round( $goal->target_value / 3600 ) . ' godz.';
|
|
$current_formatted = sprintf( '%d godz. %d min.', floor( $progress['current_value'] / 3600 ), floor( ( $progress['current_value'] % 3600 ) / 60 ) );
|
|
} elseif ( 'distance' === $goal->goal_type ) {
|
|
$target_formatted = number_format( $goal->target_value, 0, ',', ' ' ) . ' km';
|
|
$current_formatted = number_format( $progress['current_value'], 2, ',', ' ' ) . ' km';
|
|
} else { // count
|
|
$target_formatted = (int) $goal->target_value;
|
|
$current_formatted = (int) $progress['current_value'];
|
|
}
|
|
?>
|
|
<li class="mystat-goal-item">
|
|
<div class="mystat-goal-info">
|
|
<strong><?php echo esc_html( $goal->name ); ?></strong>
|
|
<small><?php echo $current_formatted; ?> / <?php echo $target_formatted; ?> (<?php echo round( $percentage, 1 ); ?>%)</small>
|
|
</div>
|
|
<div class="mystat-progress-bar-container">
|
|
<div class="mystat-progress-bar" style="width: <?php echo esc_attr( $percentage ); ?>%;"></div>
|
|
</div>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<style>
|
|
.mystat-goals-list { list-style: none; margin: 0; padding: 0; } .mystat-goal-item { margin-bottom: 15px; } .mystat-goal-info { display: flex; justify-content: space-between; margin-bottom: 5px; }
|
|
.mystat-progress-bar-container { background: #eee; border-radius: 4px; height: 18px; width: 100%; overflow: hidden; } .mystat-progress-bar { background: #3498db; height: 100%; border-radius: 4px; transition: width 0.5s ease-in-out; text-align: center; color: white; font-size: 11px; line-height: 18px; }
|
|
</style>
|
|
<?php endif; ?>
|
|
|
|
<div class="postbox" style="margin-bottom: 20px;">
|
|
<div class="postbox-header"><h2 class="hndle">Wykresy dla <?php echo esc_html( $current_year ); ?></h2></div>
|
|
<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%;">
|
|
<canvas id="mystatYearlyChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<table class="wp-list-table widefat fixed striped">
|
|
<thead>
|
|
<tr><th>Miesiąc</th><th>Dystans (km)</th><th>Kalorie (kcal)</th><th>Czas</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ( $full_year_summary as $month_data ) : ?>
|
|
<tr>
|
|
<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_calories, 0, ',', ' ' ); ?></td>
|
|
<td><?php echo esc_html( gmdate( 'H:i:s', $month_data->total_seconds ) ); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<tr class="alternate">
|
|
<th>SUMA ROCZNA</th>
|
|
<th><?php echo number_format( $total_year_distance, 2, ',', ' ' ); ?></th>
|
|
<th><?php echo number_format( $total_year_calories, 0, ',', ' ' ); ?></th>
|
|
<th><?php echo esc_html( $total_year_duration_formatted ); ?></th>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php
|
|
}
|