This commit is contained in:
2026-02-04 16:00:57 +01:00
parent 71bcc75498
commit 998f4348f3
+324 -1
View File
@@ -21,6 +21,7 @@ function mystat_activate() {
$table_activities = $wpdb->prefix . 'mystat_activities'; $table_activities = $wpdb->prefix . 'mystat_activities';
$table_event_types = $wpdb->prefix . 'mystat_event_types'; $table_event_types = $wpdb->prefix . 'mystat_event_types';
$table_equipment = $wpdb->prefix . 'mystat_equipment'; $table_equipment = $wpdb->prefix . 'mystat_equipment';
$table_goals = $wpdb->prefix . 'mystat_goals';
// SQL dla Kategorii // SQL dla Kategorii
$sql_cat = "CREATE TABLE $table_categories ( $sql_cat = "CREATE TABLE $table_categories (
@@ -45,6 +46,19 @@ function mystat_activate() {
PRIMARY KEY (id) PRIMARY KEY (id)
) $charset_collate;"; ) $charset_collate;";
// SQL dla Celów
$sql_goals = "CREATE TABLE $table_goals (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
goal_type varchar(20) NOT NULL, -- 'distance', 'duration_sec', 'count'
target_value decimal(10,2) NOT NULL,
year smallint(4) NOT NULL,
month tinyint(2) UNSIGNED DEFAULT NULL,
category_id mediumint(9) DEFAULT NULL,
PRIMARY KEY (id),
KEY category_id (category_id)
) $charset_collate;";
// SQL dla Aktywności // SQL dla Aktywności
$sql_act = "CREATE TABLE $table_activities ( $sql_act = "CREATE TABLE $table_activities (
id bigint(20) NOT NULL AUTO_INCREMENT, id bigint(20) NOT NULL AUTO_INCREMENT,
@@ -73,6 +87,7 @@ function mystat_activate() {
) $charset_collate;"; ) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql_goals );
dbDelta( $sql_equipment ); dbDelta( $sql_equipment );
dbDelta( $sql_cat ); dbDelta( $sql_cat );
dbDelta( $sql_event_types ); dbDelta( $sql_event_types );
@@ -206,6 +221,25 @@ function mystat_add_admin_menu() {
'mystat_equipment_page' 'mystat_equipment_page'
); );
$mystat_plugin_hooks[] = add_submenu_page(
'moje-statystyki',
'Użycie Sprzętu',
'Użycie Sprzętu',
'manage_options',
'mystat-equipment-usage',
'mystat_equipment_usage_page'
);
$mystat_plugin_hooks[] = add_submenu_page(
'moje-statystyki',
'Cele',
'Cele',
'manage_options',
'mystat-goals',
'mystat_goals_page'
);
$mystat_plugin_hooks[] = add_submenu_page( $mystat_plugin_hooks[] = add_submenu_page(
null, // Ukryta strona, nie pojawia się w menu null, // Ukryta strona, nie pojawia się w menu
'Szczegóły Treningu', // Tytuł strony 'Szczegóły Treningu', // Tytuł strony
@@ -444,6 +478,247 @@ function mystat_equipment_page() {
<?php <?php
} }
function mystat_equipment_usage_page() {
global $wpdb;
$table_activities = $wpdb->prefix . 'mystat_activities';
$table_equipment = $wpdb->prefix . 'mystat_equipment';
$sql = "
SELECT
eq.id,
eq.name,
SUM(a.distance) as total_distance,
SUM(TIME_TO_SEC(a.duration)) as total_seconds,
COUNT(a.id) as activity_count
FROM
$table_equipment eq
LEFT JOIN
$table_activities a ON eq.id = a.equipment_id
GROUP BY
eq.id, eq.name
ORDER BY
total_distance DESC
";
$equipment_usage = $wpdb->get_results($sql);
?>
<div class="wrap">
<h1>Użycie Sprzętu</h1>
<p>Tutaj znajdziesz podsumowanie wykorzystania Twojego sprzętu we wszystkich zarejestrowanych aktywnościach.</p>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Nazwa Sprzętu</th>
<th>Całkowity Dystans</th>
<th>Całkowity Czas</th>
<th>Liczba Aktywności</th>
</tr>
</thead>
<tbody>
<?php foreach ($equipment_usage as $item) : ?>
<tr>
<td><strong><?php echo esc_html($item->name); ?></strong></td>
<td><?php echo $item->total_distance ? number_format($item->total_distance, 2, ',', ' ') . ' km' : 'Brak danych'; ?></td>
<td><?php echo $item->total_seconds ? sprintf('%d godz. %d min.', floor($item->total_seconds / 3600), floor(($item->total_seconds % 3600) / 60)) : 'Brak danych'; ?></td>
<td><?php echo (int)$item->activity_count; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
}
/**
* Calculates the current progress for a given goal.
*
* @param object $goal The goal object from the database.
* @return array An array containing 'current_value' and 'percentage'.
*/
function mystat_get_goal_progress($goal) {
global $wpdb;
$table_activities = $wpdb->prefix . 'mystat_activities';
$sql_select = '';
switch ($goal->goal_type) {
case 'distance':
$sql_select = 'SUM(distance)';
break;
case 'duration_sec':
$sql_select = 'SUM(TIME_TO_SEC(duration))';
break;
case 'count':
$sql_select = 'COUNT(id)';
break;
default:
return ['current_value' => 0, 'percentage' => 0];
}
$where_clauses = [];
$where_clauses[] = $wpdb->prepare('YEAR(date) = %d', $goal->year);
if (!empty($goal->month)) {
$where_clauses[] = $wpdb->prepare('MONTH(date) = %d', $goal->month);
}
if (!empty($goal->category_id)) {
$where_clauses[] = $wpdb->prepare('category_id = %d', $goal->category_id);
}
$sql = "SELECT {$sql_select} FROM {$table_activities} WHERE " . implode(' AND ', $where_clauses);
$current_value = (float) $wpdb->get_var($sql);
$percentage = ($goal->target_value > 0) ? ($current_value / $goal->target_value) * 100 : 0;
return [
'current_value' => $current_value,
'percentage' => $percentage,
];
}
function mystat_goals_page() {
global $wpdb;
$table_goals = $wpdb->prefix . 'mystat_goals';
$table_categories = $wpdb->prefix . 'mystat_categories';
$message = '';
$notice_class = '';
// Handle POST requests (add/update)
if ( isset( $_POST['submit'] ) && check_admin_referer( 'mystat_manage_goal' ) ) {
$goal_id = isset( $_POST['goal_id'] ) ? intval( $_POST['goal_id'] ) : 0;
$data = [
'name' => sanitize_text_field($_POST['goal_name']),
'goal_type' => sanitize_text_field($_POST['goal_type']),
'target_value' => floatval(str_replace(',', '.', $_POST['target_value'])),
'year' => intval($_POST['year']),
'month' => $_POST['month'] === 'all' ? null : intval($_POST['month']),
'category_id' => $_POST['category_id'] === 'all' ? null : intval($_POST['category_id']),
];
if ( !empty($data['name']) && !empty($data['goal_type']) && $data['target_value'] > 0 && $data['year'] > 2000 ) {
if ( $goal_id > 0 ) { // Update
$wpdb->update( $table_goals, $data, [ 'id' => $goal_id ] );
$message = 'Cel zaktualizowany.';
$notice_class = 'notice-success';
} else { // Insert
$wpdb->insert( $table_goals, $data );
$message = 'Cel dodany.';
$notice_class = 'notice-success';
}
} else {
$message = 'Wypełnij poprawnie wszystkie wymagane pola (Nazwa, Typ, Cel, Rok).';
$notice_class = 'notice-error';
}
}
// Handle GET requests (delete)
if ( isset( $_GET['action'], $_GET['id'], $_GET['_wpnonce'] ) && $_GET['action'] === 'delete' ) {
if ( wp_verify_nonce( $_GET['_wpnonce'], 'mystat_delete_goal_' . $_GET['id'] ) ) {
$wpdb->delete( $table_goals, [ 'id' => intval( $_GET['id'] ) ] );
$message = 'Cel usunięty.';
$notice_class = 'notice-success';
}
}
// Prepare for form (for editing)
$item_to_edit = null;
if ( isset( $_GET['action'], $_GET['id'] ) && $_GET['action'] === 'edit' ) {
$item_to_edit = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_goals WHERE id = %d", intval( $_GET['id'] ) ) );
}
$goals = $wpdb->get_results( "SELECT g.*, c.name as category_name FROM $table_goals g LEFT JOIN $table_categories c ON g.category_id = c.id ORDER BY g.year DESC, g.name ASC" );
$categories = $wpdb->get_results( "SELECT * FROM $table_categories ORDER BY name ASC" );
?>
<div class="wrap">
<h1>Zarządzaj Celami</h1>
<?php if ( ! empty( $message ) ) : ?>
<div class="notice <?php echo esc_attr( $notice_class ); ?> is-dismissible"><p><?php echo esc_html( $message ); ?></p></div>
<?php endif; ?>
<div id="col-container" class="wp-clearfix">
<div id="col-left">
<div class="col-wrap">
<div class="form-wrap">
<h2><?php echo $item_to_edit ? 'Edytuj cel' : 'Dodaj nowy cel'; ?></h2>
<form method="post">
<input type="hidden" name="goal_id" value="<?php echo $item_to_edit ? esc_attr( $item_to_edit->id ) : '0'; ?>">
<?php wp_nonce_field( 'mystat_manage_goal' ); ?>
<div class="form-field form-required"><label for="goal_name">Nazwa celu</label><input type="text" name="goal_name" id="goal_name" value="<?php echo $item_to_edit ? esc_attr( $item_to_edit->name ) : ''; ?>" required></div>
<div class="form-field form-required"><label for="goal_type">Typ celu</label><select name="goal_type" id="goal_type" required><option value="distance" <?php if($item_to_edit) selected($item_to_edit->goal_type, 'distance'); ?>>Dystans (km)</option><option value="duration_sec" <?php if($item_to_edit) selected($item_to_edit->goal_type, 'duration_sec'); ?>>Czas (w godzinach)</option><option value="count" <?php if($item_to_edit) selected($item_to_edit->goal_type, 'count'); ?>>Liczba aktywności</option></select></div>
<div class="form-field form-required"><label for="target_value">Wartość docelowa</label><input type="text" name="target_value" id="target_value" value="<?php echo $item_to_edit ? esc_attr( $item_to_edit->goal_type === 'duration_sec' ? $item_to_edit->target_value / 3600 : $item_to_edit->target_value ) : ''; ?>" required><p>Dla czasu podaj wartość w godzinach (np. 100.5).</p></div>
<div class="form-field form-required"><label for="year">Rok</label><input type="number" name="year" id="year" value="<?php echo $item_to_edit ? esc_attr( $item_to_edit->year ) : current_time('Y'); ?>" required></div>
<div class="form-field"><label for="month">Miesiąc</label><select name="month" id="month"><option value="all">Cały rok</option><?php for ($i=1; $i<=12; $i++): ?><option value="<?php echo $i; ?>" <?php if($item_to_edit) selected($item_to_edit->month, $i); ?>><?php echo date_i18n('F', mktime(0,0,0,$i,10)); ?></option><?php endfor; ?></select></div>
<div class="form-field"><label for="category_id">Kategoria</label><select name="category_id" id="category_id"><option value="all">Wszystkie</option><?php foreach($categories as $cat): ?><option value="<?php echo esc_attr($cat->id); ?>" <?php if($item_to_edit) selected($item_to_edit->category_id, $cat->id); ?>><?php echo esc_html($cat->name); ?></option><?php endforeach; ?></select></div>
<?php submit_button( $item_to_edit ? 'Zaktualizuj' : 'Dodaj' ); ?>
</form>
</div>
</div>
</div>
<div id="col-right">
<div class="col-wrap">
<table class="wp-list-table widefat fixed striped">
<thead><tr><th>Cel</th><th>Postęp</th><th style="width: 100px;">Akcje</th></tr></thead>
<tbody>
<?php if (empty($goals)): ?>
<tr><td colspan="3">Brak zdefiniowanych celów.</td></tr>
<?php else: ?>
<?php foreach ( $goals as $goal ) : ?>
<?php
$is_duration = $goal->goal_type === 'duration_sec';
if ($is_duration) {
$goal->target_value = $goal->target_value * 3600; // Convert hours back to seconds for calculation
}
$progress = mystat_get_goal_progress($goal);
$percentage = min(100, $progress['percentage']);
$target_formatted = '';
$current_formatted = '';
if ($is_duration) {
$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 ($goal->goal_type === 'distance') {
$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'];
}
?>
<tr>
<td>
<strong><?php echo esc_html($goal->name); ?></strong><br>
<small>
<?php echo esc_html($goal->year); ?>
<?php if($goal->month) echo ' / ' . date_i18n('F', mktime(0,0,0,$goal->month,10)); ?>
<?php if($goal->category_name) echo ' / ' . esc_html($goal->category_name); ?>
</small>
</td>
<td>
<div class="mystat-progress-bar-container">
<div class="mystat-progress-bar" style="width: <?php echo esc_attr($percentage); ?>%;"></div>
</div>
<small><?php echo $current_formatted; ?> z <?php echo $target_formatted; ?> (<?php echo round($percentage, 1); ?>%)</small>
</td>
<td>
<a href="<?php echo esc_url( add_query_arg( [ 'action' => 'edit', 'id' => $goal->id ] ) ); ?>">Edytuj</a> |
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( [ 'action' => 'delete', 'id' => $goal->id ] ), 'mystat_delete_goal_' . $goal->id ) ); ?>" onclick="return confirm('Czy na pewno chcesz usunąć ten cel?')" style="color: #a00;">Usuń</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<style>
.mystat-progress-bar-container { background: #eee; border-radius: 4px; height: 12px; width: 100%; overflow: hidden; margin-bottom: 4px; }
.mystat-progress-bar { background: #3498db; height: 100%; border-radius: 4px; transition: width 0.5s ease-in-out; }
</style>
<?php
}
function mystat_settings_page() { function mystat_settings_page() {
?> ?>
<div class="wrap"> <div class="wrap">
@@ -547,6 +822,13 @@ function mystat_yearly_summary_page() {
$available_years = [current_time('Y')]; // Domyślny rok, jeśli brak danych $available_years = [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 // Zapytanie SQL do grupowania danych miesięcznie
$sql = $wpdb->prepare(" $sql = $wpdb->prepare("
SELECT SELECT
@@ -727,6 +1009,48 @@ function mystat_yearly_summary_page() {
</div> </div>
</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): ?>
<?php
$progress = mystat_get_goal_progress($goal);
$percentage = min(100, $progress['percentage']);
$target_formatted = '';
$current_formatted = '';
if ($goal->goal_type === 'duration_sec') {
$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 ($goal->goal_type === 'distance') {
$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" style="margin-bottom: 20px;">
<div class="postbox-header"><h2 class="hndle">Wykresy dla <?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">
@@ -2005,7 +2329,6 @@ function mystat_render_history_table() {
</div> </div>
<?php <?php
} }
?>
<?php <?php
// --- 3. SHORTCODE DO WYŚWIETLANIA NA FRONCIE --- // --- 3. SHORTCODE DO WYŚWIETLANIA NA FRONCIE ---