get_charset_collate(); $table_categories = $wpdb->prefix . 'mystat_categories'; $table_activities = $wpdb->prefix . 'mystat_activities'; $table_event_types = $wpdb->prefix . 'mystat_event_types'; $table_equipment = $wpdb->prefix . 'mystat_equipment'; // SQL dla Kategorii $sql_cat = "CREATE TABLE $table_categories ( id mediumint(9) NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL, icon varchar(50) NOT NULL, color varchar(20) NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // SQL dla Typów Wydarzeń $sql_event_types = "CREATE TABLE $table_event_types ( id mediumint(9) NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // SQL dla Sprzętu $sql_equipment = "CREATE TABLE $table_equipment ( id mediumint(9) NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // SQL dla Aktywności $sql_act = "CREATE TABLE $table_activities ( id bigint(20) NOT NULL AUTO_INCREMENT, category_id mediumint(9) NOT NULL, date date NOT NULL, title varchar(255) DEFAULT '' NOT NULL, distance decimal(10,2) DEFAULT 0.00, duration time DEFAULT '00:00:00', calories int(11) DEFAULT 0, comment text, strava_url varchar(255) DEFAULT NULL, avg_heart_rate smallint(5) UNSIGNED DEFAULT NULL, max_heart_rate smallint(5) UNSIGNED DEFAULT NULL, avg_speed decimal(5,2) DEFAULT NULL, max_speed decimal(5,2) DEFAULT NULL, avg_cadence smallint(5) UNSIGNED DEFAULT NULL, max_cadence smallint(5) UNSIGNED DEFAULT NULL, total_elevation_gain int(11) DEFAULT NULL, total_elevation_loss int(11) DEFAULT NULL, min_altitude int(11) DEFAULT NULL, max_altitude int(11) DEFAULT NULL, equipment_id mediumint(9) DEFAULT NULL, gpx_url varchar(255) DEFAULT NULL, event_type_id mediumint(9) DEFAULT NULL, PRIMARY KEY (id) ) $charset_collate;"; require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); dbDelta( $sql_equipment ); dbDelta( $sql_cat ); dbDelta( $sql_event_types ); dbDelta( $sql_act ); // Dodanie domyślnych kategorii, jeśli tabela jest pusta if ( $wpdb->get_var( "SELECT COUNT(*) FROM $table_categories" ) == 0 ) { $wpdb->insert( $table_categories, array( 'name' => 'Rower', 'icon' => 'dashicons-buddicons-groups', 'color' => '#3498db' ) ); $wpdb->insert( $table_categories, array( 'name' => 'Bieganie', 'icon' => 'dashicons-businessman', 'color' => '#e74c3c' ) ); } // Dodanie domyślnych typów wydarzeń, jeśli tabela jest pusta if ( $wpdb->get_var( "SELECT COUNT(*) FROM $table_event_types" ) == 0 ) { $default_event_types = ['Bez kategorii', 'Fitness', 'Geocaching', 'Podróżowanie', 'Rekreacyjny', 'Specjalne zdarzenie', 'Transport', 'Trening', 'Wyścig']; foreach ($default_event_types as $type_name) { $wpdb->insert( $table_event_types, array( 'name' => $type_name ) ); } // Ustawienie domyślnego typu "Trening" dla istniejących aktywności, które go nie mają $training_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $table_event_types WHERE name = %s", 'Trening' ) ); if ($training_id) { $wpdb->query( $wpdb->prepare( "UPDATE $table_activities SET event_type_id = %d WHERE event_type_id IS NULL OR event_type_id = 0", $training_id ) ); } } // Dodanie domyślnego sprzętu, jeśli tabela jest pusta if ( $wpdb->get_var( "SELECT COUNT(*) FROM $table_equipment" ) == 0 ) { $default_equipment = ['Giant Revolt', 'Cube LTD', 'Author Agang', 'Liv Tempt 4', 'Cube Acid 24', 'Mongoose BMX', 'Nextbike - Miejski']; foreach ($default_equipment as $eq_name) { $wpdb->insert( $table_equipment, array( 'name' => $eq_name ) ); } } } // --- 2. MENU ADMINA I DASHBOARD --- add_action( 'admin_menu', 'mystat_add_admin_menu' ); function mystat_add_admin_menu() { add_menu_page( 'Moje Statystyki', // Tytuł strony 'Statystyki', // Tytuł w menu 'manage_options', // Wymagane uprawnienia 'moje-statystyki', // Slug menu 'mystat_dashboard_page', // Funkcja renderująca stronę główną (dashboard) 'dashicons-chart-line', // Ikona 6 // Pozycja ); add_submenu_page( 'moje-statystyki', // Slug rodzica 'Dodaj Nowy Trening', // Tytuł strony 'Nowy trening', // Tytuł w podmenu 'manage_options', // Wymagane uprawnienia 'mystat-nowy-trening', // Slug podmenu 'mystat_add_new_page' // Funkcja renderująca stronę dodawania ); add_submenu_page( 'moje-statystyki', 'Typy Wydarzeń', 'Typy wydarzeń', 'manage_options', 'mystat-event-types', 'mystat_event_types_page' ); add_submenu_page( 'moje-statystyki', 'Sprzęt', 'Sprzęt', 'manage_options', 'mystat-equipment', 'mystat_equipment_page' ); } function mystat_dashboard_page() { echo '

Moje Statystyki Sportowe

'; mystat_render_history_table(); echo '
'; } function mystat_add_new_page() { echo '

Dodaj Nowy Trening

'; // Obsługa zapisu formularza (musi być przed renderowaniem, aby wyświetlić komunikat) mystat_handle_new_entry(); // Formularz dodawania mystat_render_add_form(); echo '
'; } function mystat_event_types_page() { global $wpdb; $table_event_types = $wpdb->prefix . 'mystat_event_types'; $message = ''; $notice_class = ''; // Handle POST requests (add/update) if ( isset( $_POST['submit'] ) && check_admin_referer( 'mystat_manage_event_type' ) ) { $name = sanitize_text_field( $_POST['event_type_name'] ); $type_id = isset( $_POST['event_type_id'] ) ? intval( $_POST['event_type_id'] ) : 0; if ( ! empty( $name ) ) { if ( $type_id > 0 ) { // Update $wpdb->update( $table_event_types, [ 'name' => $name ], [ 'id' => $type_id ] ); $message = 'Typ wydarzenia zaktualizowany.'; $notice_class = 'notice-success'; } else { // Insert $wpdb->insert( $table_event_types, [ 'name' => $name ] ); $message = 'Typ wydarzenia dodany.'; $notice_class = 'notice-success'; } } else { $message = 'Nazwa typu wydarzenia nie może być pusta.'; $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_event_type_' . $_GET['id'] ) ) { $wpdb->delete( $table_event_types, [ 'id' => intval( $_GET['id'] ) ] ); $message = 'Typ wydarzenia 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_event_types WHERE id = %d", intval( $_GET['id'] ) ) ); } $event_types = $wpdb->get_results( "SELECT * FROM $table_event_types ORDER BY name ASC" ); ?>

Typy Wydarzeń

NazwaAkcje
name ); ?>Edytuj | Usuń
prefix . 'mystat_equipment'; $message = ''; $notice_class = ''; // Handle POST requests (add/update) if ( isset( $_POST['submit'] ) && check_admin_referer( 'mystat_manage_equipment' ) ) { $name = sanitize_text_field( $_POST['equipment_name'] ); $item_id = isset( $_POST['equipment_id'] ) ? intval( $_POST['equipment_id'] ) : 0; if ( ! empty( $name ) ) { if ( $item_id > 0 ) { // Update $wpdb->update( $table_equipment, [ 'name' => $name ], [ 'id' => $item_id ] ); $message = 'Sprzęt zaktualizowany.'; $notice_class = 'notice-success'; } else { // Insert $wpdb->insert( $table_equipment, [ 'name' => $name ] ); $message = 'Sprzęt dodany.'; $notice_class = 'notice-success'; } } else { $message = 'Nazwa sprzętu nie może być pusta.'; $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_equipment_' . $_GET['id'] ) ) { $wpdb->delete( $table_equipment, [ 'id' => intval( $_GET['id'] ) ] ); $message = 'Sprzęt 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_equipment WHERE id = %d", intval( $_GET['id'] ) ) ); } $equipment_list = $wpdb->get_results( "SELECT * FROM $table_equipment ORDER BY name ASC" ); ?>

Zarządzaj Sprzętem

NazwaAkcje
name ); ?>Edytuj | Usuń

Błąd weryfikacji bezpieczeństwa formularza.

'; return; } $table_activities = $wpdb->prefix . 'mystat_activities'; // Przygotowanie danych (zamiana przecinka na kropkę w dystansie) $distance = isset($_POST['distance']) ? floatval( str_replace( ',', '.', $_POST['distance'] ) ) : 0; // Funkcja pomocnicza do zamiany pustych wartości na NULL, aby poprawnie zapisać je w bazie $null_if_empty = function($value) { return $value !== '' ? $value : null; }; $data = array( 'category_id' => intval( $_POST['category_id'] ), 'date' => sanitize_text_field( $_POST['date'] ), 'title' => sanitize_text_field( $_POST['title'] ), 'distance' => $distance, 'duration' => sanitize_text_field( $_POST['duration'] ), 'calories' => intval( $_POST['calories'] ), 'comment' => sanitize_textarea_field( $_POST['comment'] ), 'strava_url' => $null_if_empty( esc_url_raw( $_POST['strava_url'] ) ), 'avg_heart_rate' => $null_if_empty( intval( $_POST['avg_heart_rate'] ) ), 'max_heart_rate' => $null_if_empty( intval( $_POST['max_heart_rate'] ) ), 'avg_speed' => $null_if_empty( floatval( str_replace( ',', '.', $_POST['avg_speed'] ) ) ), 'max_speed' => $null_if_empty( floatval( str_replace( ',', '.', $_POST['max_speed'] ) ) ), 'avg_cadence' => $null_if_empty( intval( $_POST['avg_cadence'] ) ), 'max_cadence' => $null_if_empty( intval( $_POST['max_cadence'] ) ), 'total_elevation_gain' => $null_if_empty( intval( $_POST['total_elevation_gain'] ) ), 'total_elevation_loss' => $null_if_empty( intval( $_POST['total_elevation_loss'] ) ), 'min_altitude' => $null_if_empty( intval( $_POST['min_altitude'] ) ), 'max_altitude' => $null_if_empty( intval( $_POST['max_altitude'] ) ), 'equipment_id' => $null_if_empty( intval( $_POST['equipment_id'] ) ), 'gpx_url' => $null_if_empty( esc_url_raw( $_POST['gpx_url'] ) ), 'event_type_id' => $null_if_empty( intval( $_POST['event_type_id'] ) ), ); // Format danych dla $wpdb->insert $format = array( '%d', '%s', '%s', '%f', '%s', '%d', '%s', // Pola podstawowe '%s', '%d', '%d', '%f', '%f', '%d', '%d', // Tętno, prędkość, kadencja '%d', '%d', '%d', '%d', '%d', '%s', '%d' // Wysokość, sprzęt, linki, typ wydarzenia ); $result = $wpdb->insert( $table_activities, $data, $format ); if ( $result ) { echo '

Trening dodany pomyślnie!

'; } else { echo '

Wystąpił błąd podczas zapisu do bazy.

'; } } /** * Renderowanie formularza HTML */ function mystat_render_add_form() { global $wpdb; $table_categories = $wpdb->prefix . 'mystat_categories'; $table_event_types = $wpdb->prefix . 'mystat_event_types'; $table_equipment = $wpdb->prefix . 'mystat_equipment'; $categories = $wpdb->get_results( "SELECT * FROM $table_categories ORDER BY name ASC" ); $event_types = $wpdb->get_results( "SELECT * FROM $table_event_types ORDER BY name ASC" ); $equipment_list = $wpdb->get_results( "SELECT * FROM $table_equipment ORDER BY name ASC" ); $today = current_time( 'Y-m-d' ); ?>

Dodaj Nową Aktywność


Dane szczegółowe (opcjonalne)


Linki zewnętrzne (opcjonalne)

prefix // Jeśli tabele są "sztywne" (bez prefixu wp_), usuń $wpdb->prefix. $table_activities = $wpdb->prefix . 'mystat_activities'; $table_categories = $wpdb->prefix . 'mystat_categories'; // --- 1. OBSŁUGA USUWANIA (DELETE) --- if ( isset( $_GET['action'], $_GET['id'], $_GET['_wpnonce'] ) && $_GET['action'] === 'mystat_delete' ) { $activity_id = intval( $_GET['id'] ); // Weryfikacja bezpieczeństwa (Nonce) if ( wp_verify_nonce( $_GET['_wpnonce'], 'mystat_delete_' . $activity_id ) ) { $result = $wpdb->delete( $table_activities, array( 'id' => $activity_id ), array( '%d' ) ); if ( $result ) { echo '

Aktywność została usunięta.

'; } else { echo '

Wystąpił błąd podczas usuwania.

'; } } else { echo '

Błąd weryfikacji bezpieczeństwa (Nonce).

'; } } // --- 2. POBIERANIE DANYCH (SELECT) --- // Pobieramy ostatnie 10 wpisów, łącząc z tabelą kategorii, aby mieć nazwę i ikonę $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 {$wpdb->prefix}mystat_event_types et ON a.event_type_id = et.id LEFT JOIN {$wpdb->prefix}mystat_equipment eq ON a.equipment_id = eq.id ORDER BY a.date DESC, a.id DESC LIMIT %d ", 10); $activities = $wpdb->get_results( $sql ); // --- 3. WIDOK TABELI (HTML) --- ?>

Ostatnie Aktywności

$_REQUEST['page'], // Zachowaj obecną stronę admina 'action' => 'mystat_delete', 'id' => $row->id, '_wpnonce' => wp_create_nonce( 'mystat_delete_' . $row->id ) ), admin_url( 'admin.php' ) ); ?>
Ikona Data Tytuł Kategoria Typ Sprzęt Dystans (km) Czas Śr. prędkość Akcja
icon ) ) : ?> date ); ?> title, 6 ) ); ?> category_name ); ?> event_type_name ); ?> equipment_name ); ?> distance, 2, ',', ' ' ); ?> duration ); ?> avg_speed ? number_format( $row->avg_speed, 1, ',', ' ' ) . ' km/h' : '-'; ?> Usuń
Brak zarejestrowanych aktywności. Dodaj pierwszy trening powyżej!