feat: Dodaj funkcjonalność usuwania kampanii i wpisów historii oraz aktualizację interfejsu użytkownika

This commit is contained in:
2026-01-27 10:27:32 +01:00
parent cd5ab2b8b6
commit a590df780c
3 changed files with 278 additions and 98 deletions

View File

@@ -41,6 +41,7 @@ class Campaigns
'',
$row['bidding_strategy'],
\S::number_display( $row['budget'] ),
'<button type="button" class="btn btn-danger btn-sm delete-history-entry" data-id="' . $row['id'] . '" data-date="' . $row['date_add'] . '"><i class="fa fa-trash"></i></button>',
];
}
@@ -102,4 +103,36 @@ class Campaigns
] );
exit;
}
static public function delete_campaign()
{
$campaign_id = \S::get( 'campaign_id' );
if ( !$campaign_id )
{
echo json_encode( [ 'success' => false, 'message' => 'Nie wybrano kampanii' ] );
exit;
}
$result = \factory\Campaigns::delete_campaign( $campaign_id );
echo json_encode( [ 'success' => $result ? true : false ] );
exit;
}
static public function delete_history_entry()
{
$history_id = \S::get( 'history_id' );
if ( !$history_id )
{
echo json_encode( [ 'success' => false, 'message' => 'Nie podano wpisu do usunięcia' ] );
exit;
}
$result = \factory\Campaigns::delete_history_entry( $history_id );
echo json_encode( [ 'success' => $result ? true : false ] );
exit;
}
}

View File

@@ -34,4 +34,17 @@ class Campaigns
global $mdb;
return $mdb -> get( 'clients', 'name', [ 'id' => $client_id ] );
}
static public function delete_campaign( $campaign_id )
{
global $mdb;
$mdb -> delete( 'campaigns_history', [ 'campaign_id' => $campaign_id ] );
return $mdb -> delete( 'campaigns', [ 'id' => $campaign_id ] );
}
static public function delete_history_entry( $history_id )
{
global $mdb;
return $mdb -> delete( 'campaigns_history', [ 'id' => $history_id ] );
}
}

View File

@@ -14,12 +14,21 @@
</label>
</div>
<div class="col-md-6">
<label class="field select">
<select id="campaign_id" name="campaign_id">
<option value="">--- wybierz kampanię ---</option>
</select>
<i class="arrow double"></i>
</label>
<div class="row">
<div class="col-md-10">
<label class="field select">
<select id="campaign_id" name="campaign_id">
<option value="">--- wybierz kampanię ---</option>
</select>
<i class="arrow double"></i>
</label>
</div>
<div class="col-md-2">
<button type="button" id="delete_campaign" class="btn btn-danger btn-block" title="Usuń kampanię">
<i class="fa fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
</div>
@@ -42,7 +51,7 @@
<table class="table" id="products">
<thead>
<tr>
<th scope="col">Data</th>
<th scope="col">Data</th>
<th scope="col">ROAS (30 dni)</th>
<th scope="col">ROAS (all time)</th>
<th scope="col">Wartość konwersji (30 dni)</th>
@@ -50,6 +59,7 @@
<th scope="col">Komentarz</th>
<th scope="col">Strategia ustalania stawek</th>
<th scope="col">Budżet</th>
<th scope="col">Akcje</th>
</tr>
</thead>
<tbody>
@@ -61,6 +71,104 @@
</div>
<script type="text/javascript">
var client_id = '';
function reloadChart()
{
var campaign_id = $( '#campaign_id' ).val();
if ( !campaign_id ) return;
$.ajax({
url: '/campaigns/get_campaign_history_data_table_chart/',
method: 'POST',
data: {
campaign_id: campaign_id
},
success: function(response) {
const parsedData = JSON.parse(response);
let plotLines = [];
parsedData.comments.forEach(function(comment) {
plotLines.push({
color: '#333333',
width: 1,
value: parsedData.dates.indexOf(comment.date_add.split(' ')[0]),
dashStyle: 'Solid',
label: {
text: comment.comment,
align: 'left',
style: {
color: '#333333',
fontSize: '14px'
}
},
zIndex: 5
});
});
Highcharts.chart('container', {
title: {
text: ``,
},
subtitle: {
text: ``,
},
yAxis: {
title: {
text: ''
},
},
xAxis: {
categories: parsedData.dates,
labels: {
style: {
fontSize: '14px'
},
formatter: function() {
var date = new Date(Date.parse(this.value));
var day = date.getDate();
var month = date.getMonth() + 1;
var year = date.getFullYear();
if (day === 1 || this.isLast) {
return `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`;
} else {
return null;
}
}
},
plotLines: plotLines
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
itemStyle: {
fontSize: '14px'
}
},
plotOptions: {
series: {
label: {
connectorAllowed: false
},
pointStart: 0,
},
},
series: parsedData.chart_data,
tooltip: {
style: {
fontSize: '14px'
}
}
});
},
error: function (jqXHR, textStatus, errorThrown) {
console.error('Error AJAX:', textStatus, errorThrown);
}
});
}
$( function()
{
// load campaigns from server when client is selected
@@ -106,6 +214,120 @@
});
});
$( 'body' ).on( 'click', '#delete_campaign', function()
{
var campaign_id = $( '#campaign_id' ).val();
var campaign_name = $( '#campaign_id option:selected' ).text();
if ( !campaign_id )
{
$.alert({
title: 'Uwaga',
content: 'Najpierw wybierz kampanię do usunięcia.',
type: 'orange'
});
return;
}
$.confirm({
title: 'Potwierdzenie usunięcia',
content: 'Czy na pewno chcesz usunąć kampanię <strong>' + campaign_name + '</strong>?<br><br>Ta operacja jest nieodwracalna i usunie również całą historię kampanii.',
type: 'red',
buttons: {
confirm: {
text: 'Usuń',
btnClass: 'btn-red',
keys: ['enter'],
action: function()
{
$.ajax({
url: '/campaigns/delete_campaign/campaign_id=' + campaign_id,
type: 'POST',
success: function( response )
{
var data = JSON.parse( response );
if ( data.success )
{
$.alert({
title: 'Sukces',
content: 'Kampania została usunięta.',
type: 'green',
autoClose: 'ok|2000'
});
$( '#client_id' ).trigger( 'change' );
}
else
{
$.alert({
title: 'Błąd',
content: data.message || 'Nie udało się usunąć kampanii.',
type: 'red'
});
}
}
});
}
},
cancel: {
text: 'Anuluj'
}
}
});
});
$( 'body' ).on( 'click', '.delete-history-entry', function()
{
var btn = $( this );
var history_id = btn.data( 'id' );
var date = btn.data( 'date' );
$.confirm({
title: 'Potwierdzenie usunięcia',
content: 'Czy na pewno chcesz usunąć wpis z dnia <strong>' + date + '</strong>?',
type: 'red',
buttons: {
confirm: {
text: 'Usuń',
btnClass: 'btn-red',
keys: ['enter'],
action: function()
{
$.ajax({
url: '/campaigns/delete_history_entry/history_id=' + history_id,
type: 'POST',
success: function( response )
{
var data = JSON.parse( response );
if ( data.success )
{
$.alert({
title: 'Sukces',
content: 'Wpis został usunięty.',
type: 'green',
autoClose: 'ok|2000'
});
$( '#products' ).DataTable().ajax.reload( null, false );
reloadChart();
}
else
{
$.alert({
title: 'Błąd',
content: data.message || 'Nie udało się usunąć wpisu.',
type: 'red'
});
}
}
});
}
},
cancel: {
text: 'Anuluj'
}
}
});
});
$( 'body' ).on( 'change', '#campaign_id', function()
{
var campaign_id = $( this ).val();
@@ -128,100 +350,12 @@
{ width: '200px', name: 'spend30', orderable: false, className: "dt-type-numeric" },
{ width: 'auto', name: 'bidding_strategy', orderable: false },
{ width: 'auto', name: 'comment', orderable: false },
{ width: '150px', name: 'budget', orderable: false, className: "dt-type-numeric" }
{ width: '150px', name: 'budget', orderable: false, className: "dt-type-numeric" },
{ width: '80px', name: 'actions', orderable: false, className: "dt-center" }
],
});
$.ajax({
url: '/campaigns/get_campaign_history_data_table_chart/',
method: 'POST',
data: {
campaign_id: campaign_id
},
success: function(response) {
const parsedData = JSON.parse(response);
let plotLines = [];
parsedData.comments.forEach(function(comment) {
plotLines.push({
color: '#333333',
width: 1,
value: parsedData.dates.indexOf(comment.date_add.split(' ')[0]),
dashStyle: 'Solid',
label: {
text: comment.comment,
align: 'left',
style: {
color: '#333333',
fontSize: '14px'
}
},
zIndex: 5
});
});
Highcharts.chart('container', {
title: {
text: ``,
},
subtitle: {
text: ``,
},
yAxis: {
title: {
text: ''
},
},
xAxis: {
categories: parsedData.dates,
labels: {
style: {
fontSize: '14px'
},
formatter: function() {
var date = new Date(Date.parse(this.value));
var day = date.getDate();
var month = date.getMonth() + 1;
var year = date.getFullYear();
if (day === 1 || this.isLast) {
return `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`;
} else {
return null;
}
}
},
plotLines: plotLines
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
itemStyle: {
fontSize: '14px'
}
},
plotOptions: {
series: {
label: {
connectorAllowed: false
},
pointStart: 0,
},
},
series: parsedData.chart_data,
tooltip: {
style: {
fontSize: '14px'
}
}
});
},
error: function (jqXHR, textStatus, errorThrown) {
console.error('Error AJAX:', textStatus, errorThrown);
}
})
reloadChart();
})
});
</script>