feat: Implement client bestseller settings management with UI and backend support

This commit is contained in:
2026-03-04 09:20:35 +01:00
parent 8727c47315
commit 640d4c8b05
7 changed files with 684 additions and 23 deletions

View File

@@ -48,6 +48,24 @@
</div>
</div>
<div class="products-filters" style="margin-top:10px;">
<div class="filter-group filter-group-bestseller" style="min-width: 560px;">
<label><i class="fa-solid fa-ranking-star"></i> Bestsellery reguły</label>
<div style="display:grid;grid-template-columns:repeat(4,minmax(120px,1fr));gap:8px;">
<input type="number" id="bestseller_roas_entry" class="form-control" min="0" step="0.01" placeholder="ROAS wejście" />
<input type="number" id="bestseller_roas_exit" class="form-control" min="0" step="0.01" placeholder="ROAS wyjście" />
<input type="number" id="min_conversions" class="form-control" min="0" step="1" value="10" placeholder="Min. konwersje" />
<input type="number" id="cooldown_period" class="form-control" min="1" step="1" value="14" placeholder="Cooldown (dni)" />
</div>
<div style="margin-top:8px;">
<button type="button" id="save_bestseller_rules" class="btn btn-primary btn-sm">
<i class="fa-solid fa-floppy-disk"></i> Zapisz
</button>
<span id="bestseller_rules_preview" style="margin-left:10px;color:#555;">Spelnia: -</span>
</div>
</div>
</div>
<details id="products_scope_alerts_box" class="products-scope-alerts hide">
<summary>
<i class="fa-solid fa-triangle-exclamation"></i>
@@ -121,6 +139,8 @@ var AI_CLAUDE_ENABLED = <?= $claude_enabled ? 'true' : 'false'; ?>;
var AI_GEMINI_ENABLED = <?= $gemini_enabled ? 'true' : 'false'; ?>;
var PRODUCTS_COLUMNS_STORAGE_KEY = 'products.columns.visibility';
var PRODUCTS_LOCKED_COLUMNS = [ 0, 21 ];
var products_bestseller_settings_loading = false;
var products_bestseller_preview_timer = null;
function show_toast( message, type )
{
@@ -204,6 +224,109 @@ function products_is_locked_column( idx )
return PRODUCTS_LOCKED_COLUMNS.indexOf( Number( idx ) ) !== -1;
}
function reset_client_bestseller_settings_form()
{
$( '#bestseller_roas_entry' ).val( '' );
$( '#bestseller_roas_exit' ).val( '' );
$( '#min_conversions' ).val( '10' );
$( '#cooldown_period' ).val( '14' );
$( '#bestseller_rules_preview' ).text( 'Spelnia: -' );
}
function preview_client_bestseller_settings()
{
var client_id = $( '#client_id' ).val() || '';
if ( !client_id || products_bestseller_settings_loading )
{
$( '#bestseller_rules_preview' ).text( 'Spelnia: -' );
return;
}
$( '#bestseller_rules_preview' ).text( 'Spelnia: licze...' );
$.ajax({
url: '/products/preview_client_bestseller_settings/',
type: 'POST',
dataType: 'json',
data: {
client_id: client_id,
bestseller_roas_entry: $( '#bestseller_roas_entry' ).val(),
bestseller_roas_exit: $( '#bestseller_roas_exit' ).val(),
min_conversions: $( '#min_conversions' ).val(),
cooldown_period: $( '#cooldown_period' ).val()
}
}).done( function( res ) {
if ( res && res.status === 'ok' )
{
$( '#bestseller_rules_preview' ).text( 'Spelnia: ' + Number( res.count || 0 ) );
}
else
{
$( '#bestseller_rules_preview' ).text( 'Spelnia: -' );
}
}).fail( function() {
$( '#bestseller_rules_preview' ).text( 'Spelnia: -' );
});
}
function load_client_bestseller_settings( client_id )
{
if ( !client_id )
{
reset_client_bestseller_settings_form();
return $.Deferred().resolve().promise();
}
products_bestseller_settings_loading = true;
return $.ajax({
url: '/products/get_client_bestseller_settings/client_id=' + client_id,
type: 'GET',
dataType: 'json'
}).done( function( res ) {
var settings = ( res && res.settings ) ? res.settings : {};
$( '#bestseller_roas_entry' ).val( settings.bestseller_roas_entry == null ? '' : settings.bestseller_roas_entry );
$( '#bestseller_roas_exit' ).val( settings.bestseller_roas_exit == null ? '' : settings.bestseller_roas_exit );
$( '#min_conversions' ).val( settings.min_conversions != null ? settings.min_conversions : 10 );
$( '#cooldown_period' ).val( settings.cooldown_period != null ? settings.cooldown_period : 14 );
}).fail( function() {
show_toast( 'Nie udalo sie pobrac ustawien bestsellera.', 'error' );
}).always( function() {
products_bestseller_settings_loading = false;
preview_client_bestseller_settings();
});
}
function save_client_bestseller_settings()
{
var client_id = $( '#client_id' ).val() || '';
if ( !client_id || products_bestseller_settings_loading )
{
return;
}
$.ajax({
url: '/products/save_client_bestseller_settings/',
type: 'POST',
dataType: 'json',
data: {
client_id: client_id,
bestseller_roas_entry: $( '#bestseller_roas_entry' ).val(),
bestseller_roas_exit: $( '#bestseller_roas_exit' ).val(),
min_conversions: $( '#min_conversions' ).val(),
cooldown_period: $( '#cooldown_period' ).val()
},
error: function() {
show_toast( 'Nie udalo sie zapisac ustawien bestsellera.', 'error' );
},
success: function() {
preview_client_bestseller_settings();
}
});
}
function products_get_saved_columns_visibility( columns_count )
{
var raw = products_storage_get( PRODUCTS_COLUMNS_STORAGE_KEY );
@@ -1107,6 +1230,7 @@ $( function()
$( '#products_search' ).val( '' );
$( '#products_cl4' ).val( '' );
update_delete_ad_group_button_state();
load_client_bestseller_settings( client_id );
load_products_campaigns( client_id, '' ).done( function() {
load_products_ad_groups( '', '' ).done( function() {
@@ -1226,6 +1350,7 @@ $( function()
$( '#products_search' ).val( savedSearch );
$( '#products_cl4' ).val( savedCl4 );
load_client_bestseller_settings( $( '#client_id' ).val() || '' );
load_cl4_suggestions( $( '#client_id' ).val() || '' );
@@ -1435,6 +1560,17 @@ $( function()
});
});
$( 'body' ).on( 'click', '#save_bestseller_rules', function()
{
save_client_bestseller_settings();
});
$( 'body' ).on( 'input change', '#bestseller_roas_entry, #bestseller_roas_exit, #min_conversions, #cooldown_period', function()
{
clearTimeout( products_bestseller_preview_timer );
products_bestseller_preview_timer = setTimeout( preview_client_bestseller_settings, 300 );
});
// CL4 autocomplete — datalist z unikalnymi wartościami
var cl4_values_cache = [];
var cl4_datalist_id = 'cl4-suggestions';