Files
2026-04-22 14:00:54 +02:00

287 lines
11 KiB
PHP

<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
function statpress_yearly_summary_page() {
global $wpdb;
$table_activities = $wpdb->prefix . 'statpress_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 . 'statpress_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( 'statpress-chart-loader', false );
wp_enqueue_script( 'statpress-chart-loader' );
$chart_configs = array(
'distance' => array(
'label' => 'Dystans (km)',
'data' => $chart_datasets['distance'],
'backgroundColor' => 'rgba(26, 115, 232, 0.5)', /* Google Blue */
'borderColor' => 'rgba(26, 115, 232, 1)',
'yAxisLabel' => 'Kilometry',
),
'duration' => array(
'label' => 'Czas trwania (godz.)',
'data' => $chart_datasets['duration'],
'backgroundColor' => 'rgba(24, 128, 56, 0.5)', /* Google Green */
'borderColor' => 'rgba(24, 128, 56, 1)',
'yAxisLabel' => 'Godziny',
),
'calories' => array(
'label' => 'Kalorie (kcal)',
'data' => $chart_datasets['calories'],
'backgroundColor' => 'rgba(217, 48, 37, 0.5)', /* Google Red */
'borderColor' => 'rgba(217, 48, 37, 1)',
'yAxisLabel' => 'kcal',
),
'activities' => array(
'label' => 'Liczba aktywności',
'data' => $chart_datasets['activities'],
'backgroundColor' => 'rgba(249, 171, 0, 0.5)', /* Google Yellow */
'borderColor' => 'rgba(249, 171, 0, 1)',
'yAxisLabel' => 'Ilość',
),
);
wp_add_inline_script(
'statpress-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("statpressYearlyChart").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>
<hr class="wp-header-end">
<div style="margin-bottom: 20px;">
<form method="get" style="display: flex; gap: 10px; align-items: center;">
<input type="hidden" name="page" value="statpress-yearly-summary">
<label for="filter-by-year" style="font-weight: 500; color: #3c4043;">Filtruj według roku:</label>
<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, array( 'style' => 'margin: 0;' ) ); ?>
</form>
</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="statpress-goals-list">
<?php
foreach ( $goals_for_year as $goal ) :
$progress = statpress_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="statpress-goal-item">
<div class="statpress-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="statpress-progress-bar-container">
<div class="statpress-progress-bar" style="width: <?php echo esc_attr( $percentage ); ?>%;"></div>
</div>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?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="statpressYearlyChart"></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
}