- Updated SCSS styles for new campaign sync buttons and dropdowns. - Refactored main_view.php to replace the single select for campaigns with a multi-select dropdown. - Added JavaScript functions to handle dropdown interactions and sync status updates. - Introduced sync status bars for clients in main_view.php. - Created new database migrations for client sync flags and cron sync status tracking.
271 lines
9.4 KiB
PHP
271 lines
9.4 KiB
PHP
<div class="clients-page">
|
|
<div class="clients-header">
|
|
<h2><i class="fa-solid fa-building"></i> Klienci</h2>
|
|
<button type="button" class="btn btn-success" onclick="openClientForm()">
|
|
<i class="fa-solid fa-plus mr5"></i>Dodaj klienta
|
|
</button>
|
|
</div>
|
|
|
|
<div class="clients-table-wrap">
|
|
<table class="table" id="clients-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 60px;">#ID</th>
|
|
<th>Nazwa klienta</th>
|
|
<th>Google Ads Customer ID</th>
|
|
<th>Merchant Account ID</th>
|
|
<th>Dane od</th>
|
|
<th style="width: 160px;">Sync</th>
|
|
<th style="width: 120px; text-align: center;">Akcje</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if ( $this -> clients ): ?>
|
|
<?php foreach ( $this -> clients as $client ): ?>
|
|
<tr data-id="<?= $client['id']; ?>">
|
|
<td class="client-id"><?= $client['id']; ?></td>
|
|
<td class="client-name"><?= htmlspecialchars( $client['name'] ); ?></td>
|
|
<td>
|
|
<?php if ( $client['google_ads_customer_id'] ): ?>
|
|
<span class="badge-id"><?= htmlspecialchars( $client['google_ads_customer_id'] ); ?></span>
|
|
<?php else: ?>
|
|
<span class="text-muted">— brak —</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if ( !empty( $client['google_merchant_account_id'] ) ): ?>
|
|
<span class="badge-id"><?= htmlspecialchars( $client['google_merchant_account_id'] ); ?></span>
|
|
<?php else: ?>
|
|
<span class="text-muted">— brak —</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if ( $client['google_ads_start_date'] ): ?>
|
|
<?= $client['google_ads_start_date']; ?>
|
|
<?php else: ?>
|
|
<span class="text-muted">— brak —</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="client-sync" data-sync-id="<?= $client['id']; ?>"><span class="text-muted">—</span></td>
|
|
<td class="actions-cell">
|
|
<?php if ( $client['google_ads_customer_id'] ): ?>
|
|
<button type="button" class="btn-icon btn-icon-sync" onclick="syncClient(<?= $client['id']; ?>, this)" title="Pobierz dane z Google Ads">
|
|
<i class="fa-solid fa-rotate"></i>
|
|
</button>
|
|
<?php endif; ?>
|
|
<button type="button" class="btn-icon btn-icon-edit" onclick="editClient(<?= $client['id']; ?>)" title="Edytuj">
|
|
<i class="fa-solid fa-pen"></i>
|
|
</button>
|
|
<button type="button" class="btn-icon btn-icon-delete" onclick="deleteClient(<?= $client['id']; ?>, '<?= htmlspecialchars( addslashes( $client['name'] ) ); ?>')" title="Usuń">
|
|
<i class="fa-solid fa-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr>
|
|
<td colspan="7" class="empty-state">
|
|
<i class="fa-solid fa-building"></i>
|
|
<p>Brak klientów. Dodaj pierwszego klienta.</p>
|
|
</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Dodaj / Edytuj klienta -->
|
|
<div class="default_popup" id="client-modal">
|
|
<div class="popup_content" style="max-width: 520px;">
|
|
<div class="popup_header">
|
|
<div class="title" id="client-modal-title">Dodaj klienta</div>
|
|
<div class="close"><i class="fa-solid fa-xmark"></i></div>
|
|
</div>
|
|
<div class="popup_body">
|
|
<form method="POST" id="client-form" action="/clients/save">
|
|
<input type="hidden" name="id" id="client-id" value="" />
|
|
<div class="settings-field">
|
|
<label for="client-name">Nazwa klienta</label>
|
|
<input type="text" id="client-name" name="name" class="form-control" required placeholder="np. Firma XYZ" />
|
|
</div>
|
|
<div class="settings-field">
|
|
<label for="client-gads-id">Google Ads Customer ID</label>
|
|
<input type="text" id="client-gads-id" name="google_ads_customer_id" class="form-control" placeholder="np. 123-456-7890 (opcjonalnie)" />
|
|
</div>
|
|
<div class="settings-field">
|
|
<label for="client-gmc-id">Merchant Account ID</label>
|
|
<input type="text" id="client-gmc-id" name="google_merchant_account_id" class="form-control" placeholder="np. 123456789 (opcjonalnie)" />
|
|
<small class="text-muted">ID konta Merchant Center przypisane do klienta</small>
|
|
</div>
|
|
<div class="settings-field">
|
|
<label for="client-gads-start">Pobieraj dane od</label>
|
|
<input type="date" id="client-gads-start" name="google_ads_start_date" class="form-control" />
|
|
<small class="text-muted">Data od której CRON zacznie pobierać dane z Google Ads API</small>
|
|
</div>
|
|
<div style="margin-top: 20px; display: flex; gap: 10px;">
|
|
<button type="submit" class="btn btn-success"><i class="fa-solid fa-check mr5"></i>Zapisz</button>
|
|
<button type="button" class="btn btn-secondary" onclick="closeClientForm()">Anuluj</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
function openClientForm()
|
|
{
|
|
$( '#client-modal-title' ).text( 'Dodaj klienta' );
|
|
$( '#client-id' ).val( '' );
|
|
$( '#client-name' ).val( '' );
|
|
$( '#client-gads-id' ).val( '' );
|
|
$( '#client-gmc-id' ).val( '' );
|
|
$( '#client-gads-start' ).val( '' );
|
|
$( '#client-modal' ).fadeIn();
|
|
}
|
|
|
|
function closeClientForm()
|
|
{
|
|
$( '#client-modal' ).fadeOut();
|
|
}
|
|
|
|
function editClient( id )
|
|
{
|
|
$.getJSON( '/clients/get/id=' + id, function( data ) {
|
|
$( '#client-modal-title' ).text( 'Edytuj klienta' );
|
|
$( '#client-id' ).val( data.id );
|
|
$( '#client-name' ).val( data.name );
|
|
$( '#client-gads-id' ).val( data.google_ads_customer_id || '' );
|
|
$( '#client-gmc-id' ).val( data.google_merchant_account_id || '' );
|
|
$( '#client-gads-start' ).val( data.google_ads_start_date || '' );
|
|
$( '#client-modal' ).fadeIn();
|
|
} );
|
|
}
|
|
|
|
function syncClient( id, btn )
|
|
{
|
|
var $btn = $( btn );
|
|
var $icon = $btn.find( 'i' );
|
|
|
|
$btn.prop( 'disabled', true );
|
|
$icon.removeClass( 'fa-rotate' ).addClass( 'fa-spinner fa-spin' );
|
|
|
|
$.post( '/clients/force_sync', { id: id }, function( response )
|
|
{
|
|
var data = JSON.parse( response );
|
|
|
|
$btn.prop( 'disabled', false );
|
|
$icon.removeClass( 'fa-spinner fa-spin' ).addClass( 'fa-rotate' );
|
|
|
|
if ( data.success )
|
|
{
|
|
$btn.addClass( 'is-queued' );
|
|
|
|
$.alert({
|
|
title: 'Zakolejkowano',
|
|
content: 'Klient zostal oznaczony do ponownej synchronizacji. Przy najblizszym uruchomieniu CRON dane kampanii i produktow zostana pobrane od nowa dla calego okna konwersji.',
|
|
type: 'green',
|
|
autoClose: 'ok|3000'
|
|
});
|
|
}
|
|
else
|
|
{
|
|
$.alert({
|
|
title: 'Blad',
|
|
content: data.message || 'Nie udalo sie oznaczyc klienta.',
|
|
type: 'red'
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function deleteClient( id, name )
|
|
{
|
|
$.confirm( {
|
|
title: 'Potwierdzenie',
|
|
content: 'Czy na pewno chcesz usunąć klienta <strong>' + name + '</strong>?',
|
|
type: 'red',
|
|
onContentReady: function() {
|
|
if ( this['$$confirm'] && this['$$confirm'].length )
|
|
{
|
|
this['$$confirm'].trigger( 'focus' );
|
|
}
|
|
},
|
|
buttons: {
|
|
confirm: {
|
|
text: 'Usuń',
|
|
btnClass: 'btn-red',
|
|
keys: [ 'enter' ],
|
|
action: function() {
|
|
$.post( '/clients/delete', { id: id }, function( response ) {
|
|
var data = JSON.parse( response );
|
|
if ( data.success ) {
|
|
$( 'tr[data-id="' + id + '"]' ).fadeOut( 300, function() { $( this ).remove(); } );
|
|
}
|
|
} );
|
|
}
|
|
},
|
|
cancel: {
|
|
text: 'Anuluj'
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
|
|
// Zamknij modal klawiszem Escape
|
|
$( document ).on( 'keydown', function( e ) {
|
|
if ( e.key === 'Escape' ) closeClientForm();
|
|
} );
|
|
|
|
// Zamknij modal kliknięciem w tło
|
|
$( '#client-modal' ).on( 'click', function( e ) {
|
|
if ( e.target === this ) closeClientForm();
|
|
} );
|
|
|
|
// --- Sync status bars ---
|
|
function renderSyncBar( label, done, total )
|
|
{
|
|
var pct = total > 0 ? Math.round( done / total * 100 ) : 0;
|
|
var cls = pct >= 100 ? 'is-done' : ( pct > 0 ? 'is-active' : '' );
|
|
|
|
return '<div class="client-sync-row">' +
|
|
'<span class="client-sync-label">' + label + '</span>' +
|
|
'<div class="client-sync-track"><div class="client-sync-fill ' + cls + '" style="width:' + pct + '%"></div></div>' +
|
|
'<span class="client-sync-pct">' + pct + '%</span>' +
|
|
'</div>';
|
|
}
|
|
|
|
function loadSyncStatus()
|
|
{
|
|
$.getJSON( '/clients/sync_status', function( resp )
|
|
{
|
|
if ( resp.status !== 'ok' ) return;
|
|
|
|
$( '.client-sync' ).each( function()
|
|
{
|
|
var $cell = $( this );
|
|
var id = $cell.data( 'sync-id' );
|
|
var info = resp.data[ id ];
|
|
|
|
if ( !info )
|
|
{
|
|
$cell.html( '<span class="text-muted">—</span>' );
|
|
return;
|
|
}
|
|
|
|
var html = '<div class="client-sync-bars">';
|
|
if ( info.campaigns ) html += renderSyncBar( 'K:', info.campaigns[0], info.campaigns[1] );
|
|
if ( info.products ) html += renderSyncBar( 'P:', info.products[0], info.products[1] );
|
|
html += '</div>';
|
|
|
|
$cell.html( html );
|
|
} );
|
|
} );
|
|
}
|
|
|
|
$( document ).ready( function() {
|
|
loadSyncStatus();
|
|
setInterval( loadSyncStatus, 15000 );
|
|
} );
|
|
</script>
|