From 9d62cfc8454ac7e6e83dad07d400f265966e5d02 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Fri, 30 Jan 2026 00:27:44 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Dodaj=20funkcjonalno=C5=9B=C4=87=20usuw?= =?UTF-8?q?ania=20zaznaczonych=20produkt=C3=B3w=20w=20interfejsie=20u?= =?UTF-8?q?=C5=BCytkownika?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/ftp-kr.sync.cache.json | 20 ++-- autoload/controls/class.Products.php | 16 ++++ autoload/factory/class.Products.php | 11 +++ templates/products/main_view.php | 133 +++++++++++++++++++++++---- 4 files changed, 152 insertions(+), 28 deletions(-) diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index 46b4757..7f932ce 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -41,8 +41,8 @@ }, "class.Products.php": { "type": "-", - "size": 12516, - "lmtime": 1763678563804, + "size": 13723, + "lmtime": 1769467026122, "modified": false }, "class.Site.php": { @@ -61,9 +61,9 @@ "factory": { "class.Campaigns.php": { "type": "-", - "size": 1089, + "size": 1245, "lmtime": 0, - "modified": false + "modified": true }, "class.Cron.php": { "type": "-", @@ -73,8 +73,8 @@ }, "class.Products.php": { "type": "-", - "size": 6067, - "lmtime": 1760996968673, + "size": 6644, + "lmtime": 1769467013018, "modified": false }, "class.Users.php": { @@ -161,14 +161,14 @@ "products": { "main_view.php": { "type": "-", - "size": 13363, + "size": 15258, "lmtime": 1763678650806, - "modified": false + "modified": true }, "product_history.php": { "type": "-", - "size": 10103, - "lmtime": 1764629661097, + "size": 12423, + "lmtime": 1769467103988, "modified": false } }, diff --git a/autoload/controls/class.Products.php b/autoload/controls/class.Products.php index 06eb92d..4f76e12 100644 --- a/autoload/controls/class.Products.php +++ b/autoload/controls/class.Products.php @@ -167,6 +167,7 @@ class Products $roasCellHtml = '
'.$roasNumeric.$roasPerfBar.'
'; $data['data'][] = [ + '', // checkbox column $row['product_id'], $row['offer_id'], '
@@ -208,6 +209,21 @@ class Products exit; } + static public function delete_products() { + $product_ids = \S::get( 'product_ids' ); + + if ( !is_array( $product_ids ) || empty( $product_ids ) ) { + echo json_encode( [ 'status' => 'error', 'message' => 'Brak produktów do usunięcia' ] ); + exit; + } + + if ( \factory\Products::delete_products( $product_ids ) ) + echo json_encode( [ 'status' => 'ok' ] ); + else + echo json_encode( [ 'status' => 'error', 'message' => 'Błąd podczas usuwania produktów' ] ); + exit; + } + static public function save_min_roas() { $product_id = \S::get( 'product_id' ); diff --git a/autoload/factory/class.Products.php b/autoload/factory/class.Products.php index 7e46e44..567be87 100644 --- a/autoload/factory/class.Products.php +++ b/autoload/factory/class.Products.php @@ -8,6 +8,17 @@ class Products return true; } + static public function delete_products( $product_ids ) { + global $mdb; + if ( empty( $product_ids ) || !is_array( $product_ids ) ) { + return false; + } + foreach ( $product_ids as $product_id ) { + $mdb -> delete( 'products', [ 'id' => $product_id ] ); + } + return true; + } + static public function get_product_comments( $product_id ) { global $mdb; diff --git a/templates/products/main_view.php b/templates/products/main_view.php index 3a14a5c..e14416a 100644 --- a/templates/products/main_view.php +++ b/templates/products/main_view.php @@ -27,9 +27,15 @@
+
+ +
+ @@ -128,24 +134,29 @@ }, processing: true, serverSide: true, + autoWidth: false, columns: [ + { width: '30px', orderable: false, className: 'select-checkbox', render: function(data, type, row) { + return ''; + } + }, + { width: '50px', orderable: false }, + { width: '80px', name: 'offer_id' }, + { name: 'name' }, + { width: '50px', name: 'impressions' }, + { width: '150px', name: 'impressions_30' }, + { width: '50px', name: 'clicks' }, + { width: '150px', name: 'clicks_30' }, + { width: '50px', name: 'ctr' }, + { width: '100px', name: 'cost', className: "dt-type-numeric" }, + { width: '50px', name: 'cpc', className: "dt-type-numeric" }, + { width: '50px', name: 'conversions' }, + { width: '125px', name: 'conversions_value', className: "dt-type-numeric" }, + { width: '70px', name: 'roas' }, + { width: '70px', name: 'min_roas' }, + { width: '50px', name: 'cl3', orderable: false }, { width: '100px', orderable: false }, - { width: '100px', name: 'offer_id' }, - { width: 'auto', name: 'name' }, - { width: 'auto', name: 'impressions' }, - { width: 'auto', name: 'impressions_30' }, - { width: 'auto', name: 'clicks' }, - { width: 'auto', name: 'clicks_30' }, - { width: 'auto', name: 'ctr' }, - { width: 'auto', name: 'cost', className: "dt-type-numeric" }, - { width: 'auto', name: 'cpc', className: "dt-type-numeric" }, - { width: 'auto', name: 'conversions' }, - { width: 'auto', name: 'conversions_value', className: "dt-type-numeric" }, - { width: 'auto', name: 'roas' }, - { width: '100px', name: 'min_roas' }, - { width: 'auto', name: 'cl3', orderable: false }, - { width: '200px', orderable: false }, - { width: '100px', orderable: false }], + { width: '50px', orderable: false }], order: [ [ 5, 'desc' ] ] }); }); @@ -184,9 +195,9 @@ } } }); - // usuń wiersz z tabeli + // usuń wiersz z tabeli (zachowaj bieżącą stronę) var table = $('#products').DataTable(); - table.row(row).remove().draw(); + table.row(row).remove().draw(false); } else { @@ -439,5 +450,91 @@ } }); }); + + // Funkcja aktualizująca licznik i stan przycisku + function updateSelectedCount() { + var count = $('.product-checkbox:checked').length; + $('#selected-count').text(count); + $('#delete-selected-products').prop('disabled', count === 0); + } + + // Zaznacz/odznacz wszystkie produkty na bieżącej stronie + $('body').on('change', '#select-all-products', function() { + var isChecked = $(this).is(':checked'); + $('.product-checkbox').prop('checked', isChecked); + updateSelectedCount(); + }); + + // Obsługa pojedynczych checkboxów + $('body').on('change', '.product-checkbox', function() { + updateSelectedCount(); + // Aktualizuj stan checkboxa "zaznacz wszystkie" + var allChecked = $('.product-checkbox').length === $('.product-checkbox:checked').length; + $('#select-all-products').prop('checked', allChecked); + }); + + // Reset checkboxa "zaznacz wszystkie" przy zmianie strony/sortowaniu + $('#products').on('draw.dt', function() { + $('#select-all-products').prop('checked', false); + updateSelectedCount(); + }); + + // Usuwanie zaznaczonych produktów + $('body').on('click', '#delete-selected-products', function() { + var selectedIds = []; + $('.product-checkbox:checked').each(function() { + selectedIds.push($(this).val()); + }); + + if (selectedIds.length === 0) { + $.alert('Nie zaznaczono żadnych produktów.'); + return; + } + + $.confirm({ + title: 'Potwierdzenie', + content: 'Czy na pewno chcesz usunąć ' + selectedIds.length + ' zaznaczonych produktów?', + buttons: { + confirm: { + text: 'Usuń', + keys: ['enter'], + action: function() { + $.ajax({ + url: '/products/delete_products/', + type: 'POST', + data: { + product_ids: selectedIds + }, + success: function(response) { + var data = JSON.parse(response); + if (data.status == 'ok') { + $.alert({ + title: 'Sukces', + content: 'Usunięto ' + selectedIds.length + ' produktów.', + autoClose: 'ok|2000', + buttons: { + ok: function() {} + } + }); + // Odśwież tabelę zachowując bieżącą stronę + var table = $('#products').DataTable(); + table.ajax.reload(null, false); + } else { + $.alert('Błąd: ' + data.message); + } + }, + error: function() { + $.alert('Wystąpił błąd podczas usuwania produktów. Spróbuj ponownie.'); + } + }); + } + }, + cancel: { + text: 'Anuluj', + action: function() {} + } + } + }); + }); }); \ No newline at end of file
Id Id oferty Nazwa produktu