Add comment form alongside chart in product history
- Introduced a new layout for the product history page, integrating a comment form next to the chart. - Styled the comment form with SCSS for better user experience. - Implemented form submission via AJAX to save comments without page reload. - Set default date in the comment form to today's date. - Enhanced error handling for AJAX requests related to comment submission.
This commit is contained in:
@@ -36,6 +36,21 @@ class Products
|
|||||||
] );
|
] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function comment_add()
|
||||||
|
{
|
||||||
|
$product_id = \S::get( 'product_id' );
|
||||||
|
$date = \S::get( 'date' );
|
||||||
|
$comment = \S::get( 'comment' );
|
||||||
|
|
||||||
|
if ( \factory\Products::add_product_comment( $product_id, $comment, $date ) )
|
||||||
|
{
|
||||||
|
echo json_encode( [ 'status' => 'ok' ] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo json_encode( [ 'status' => 'error' ] );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
static public function get_products()
|
static public function get_products()
|
||||||
{
|
{
|
||||||
$client_id = \S::get( 'client_id' );
|
$client_id = \S::get( 'client_id' );
|
||||||
@@ -95,7 +110,7 @@ class Products
|
|||||||
</div>',
|
</div>',
|
||||||
$row['impressions'],
|
$row['impressions'],
|
||||||
$row['impressions_30'],
|
$row['impressions_30'],
|
||||||
'<span style="color: ' . ( $row['clicks'] > 100 ? '#57b951' : '' ) . '">' . $row['clicks'] . '</span>',
|
'<span style="color: ' . ( $row['clicks'] > 200 ? '#57b951' : '' ) . '">' . $row['clicks'] . '</span>',
|
||||||
$row['clicks_30'],
|
$row['clicks_30'],
|
||||||
round( $row['ctr'], 2 ) . '%',
|
round( $row['ctr'], 2 ) . '%',
|
||||||
\S::number_display( $row['cost'] ),
|
\S::number_display( $row['cost'] ),
|
||||||
@@ -134,7 +149,7 @@ class Products
|
|||||||
|
|
||||||
if ( \factory\Products::set_product_data( $product_id, 'custom_label_4', $custom_label_4 ) )
|
if ( \factory\Products::set_product_data( $product_id, 'custom_label_4', $custom_label_4 ) )
|
||||||
{
|
{
|
||||||
\factory\Products::add_product_comment( $product_id, 1, 'Zmiana etykiety 4 na: ' . $custom_label_4 );
|
\factory\Products::add_product_comment( $product_id, 'Zmiana etykiety 4 na: ' . $custom_label_4 );
|
||||||
echo json_encode( [ 'status' => 'ok' ] );
|
echo json_encode( [ 'status' => 'ok' ] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -254,7 +269,7 @@ class Products
|
|||||||
echo json_encode([
|
echo json_encode([
|
||||||
'chart_data' => $chart_data,
|
'chart_data' => $chart_data,
|
||||||
'dates' => $dates,
|
'dates' => $dates,
|
||||||
'comments' => []
|
'comments' => \factory\Products::get_product_comments( $product_id ),
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@@ -266,7 +281,7 @@ class Products
|
|||||||
|
|
||||||
if ( \factory\Products::set_product_data( $product_id, 'title', $custom_title ) )
|
if ( \factory\Products::set_product_data( $product_id, 'title', $custom_title ) )
|
||||||
{
|
{
|
||||||
\factory\Products::add_product_comment( $product_id, 1, 'Zmiana nazwy produktu na: ' . $custom_title );
|
\factory\Products::add_product_comment( $product_id, 'Zmiana nazwy produktu na: ' . $custom_title );
|
||||||
echo json_encode( [ 'status' => 'ok' ] );
|
echo json_encode( [ 'status' => 'ok' ] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
namespace factory;
|
namespace factory;
|
||||||
class Products
|
class Products
|
||||||
{
|
{
|
||||||
|
static public function get_product_comments( $product_id )
|
||||||
|
{
|
||||||
|
global $mdb;
|
||||||
|
return $mdb -> query( 'SELECT comment, date_add FROM products_comments WHERE product_id = \'' . $product_id . '\' ORDER BY date_add DESC' ) -> fetchAll( \PDO::FETCH_ASSOC );
|
||||||
|
}
|
||||||
|
|
||||||
static public function get_min_roas( $product_id )
|
static public function get_min_roas( $product_id )
|
||||||
{
|
{
|
||||||
global $mdb;
|
global $mdb;
|
||||||
@@ -93,13 +99,18 @@ class Products
|
|||||||
return $mdb -> query( 'SELECT SUM(clicks) FROM products_history WHERE product_id = \'' . $product_id . '\' AND date_add >= \'' . date( 'Y-m-d', strtotime( '-30 days', time() ) ) . '\'' ) -> fetchColumn();
|
return $mdb -> query( 'SELECT SUM(clicks) FROM products_history WHERE product_id = \'' . $product_id . '\' AND date_add >= \'' . date( 'Y-m-d', strtotime( '-30 days', time() ) ) . '\'' ) -> fetchColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function add_product_comment( $product_id, $type, $comment )
|
static public function add_product_comment( $product_id, $comment, $date = null )
|
||||||
{
|
{
|
||||||
global $mdb;
|
global $mdb;
|
||||||
|
|
||||||
if ( $mdb -> count( 'products_comments', [ 'AND' => [ 'product_id' => $product_id, 'type' => $type, 'comment' => $comment, 'date_add' => date( 'Y-m-d' ) ] ] ) )
|
if ( !$date )
|
||||||
$mdb -> update( 'products_comments', [ 'date_add' => date( 'Y-m-d H:i:s' ) ], [ 'AND' => [ 'product_id' => $product_id, 'type' => $type, 'comment' => $comment, 'date_add' => date( 'Y-m-d' ) ] ] );
|
$date = date( 'Y-m-d' );
|
||||||
else
|
else
|
||||||
$mdb -> insert( 'products_comments', [ 'product_id' => $product_id, 'type' => $type, 'comment' => $comment, 'date_add' => date( 'Y-m-d' ) ] );
|
$date = date( 'Y-m-d', strtotime( $date ) );
|
||||||
|
|
||||||
|
if ( $mdb -> count( 'products_comments', [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] ) )
|
||||||
|
return $mdb -> update( 'products_comments', [ 'comment' => $comment ], [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] );
|
||||||
|
else
|
||||||
|
return $mdb -> insert( 'products_comments', [ 'product_id' => $product_id, 'comment' => $comment, 'date_add' => $date ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1273,4 +1273,66 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-with-form {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-area {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form {
|
||||||
|
width: 360px;
|
||||||
|
/* stała, wygodna szerokość prawej kolumny */
|
||||||
|
flex: 0 0 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form .form-group {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form input[type="date"],
|
||||||
|
.comment-form textarea {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form textarea {
|
||||||
|
min-height: 120px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form .btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 8px 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 0;
|
||||||
|
background: #337ab7;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form .btn[disabled] {
|
||||||
|
opacity: .6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form .hint {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,32 @@
|
|||||||
<div class="admin-form theme-primary">
|
<div class="admin-form theme-primary">
|
||||||
<div class="panel heading-border panel-primary">
|
<div class="panel heading-border panel-primary">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<figure class="highcharts-figure">
|
<div class="chart-with-form">
|
||||||
<div id="container"></div>
|
<div class="chart-area">
|
||||||
</figure>
|
<figure class="highcharts-figure">
|
||||||
|
<div id="container"></div>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PRAWY PANEL: formularz komentarza -->
|
||||||
|
<aside class="comment-form admin-form theme-primary">
|
||||||
|
<form id="product-comment-form" autocomplete="off">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="comment_date">Data</label>
|
||||||
|
<input type="date" id="comment_date" name="date" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="comment_text">Komentarz</label>
|
||||||
|
<textarea id="comment_text" name="comment" placeholder="Wpisz komentarz..." required></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn" id="save_comment">Zapisz komentarz</button>
|
||||||
|
</form>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="admin-form theme-primary">
|
<div class="admin-form theme-primary">
|
||||||
<div class="panel heading-border panel-primary">
|
<div class="panel heading-border panel-primary">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
@@ -24,24 +44,34 @@
|
|||||||
<th scope="col">Data</th>
|
<th scope="col">Data</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody></tbody>
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://code.highcharts.com/highcharts.js"></script>
|
<script src="https://code.highcharts.com/highcharts.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$( function() {
|
$(function() {
|
||||||
var client_id = <?= $this -> client_id;?>;
|
var client_id = <?= $this -> client_id;?>;
|
||||||
var product_id = <?= $this -> product_id;?>;
|
var product_id = <?= $this -> product_id;?>;
|
||||||
|
|
||||||
table = $( '#products' ).DataTable();
|
// Ustaw domyślnie dzisiejszą datę w formularzu (YYYY-MM-DD)
|
||||||
|
(function presetToday() {
|
||||||
|
var el = document.getElementById('comment_date');
|
||||||
|
if (!el) return;
|
||||||
|
var d = new Date();
|
||||||
|
var m = String(d.getMonth() + 1).padStart(2, '0');
|
||||||
|
var day = String(d.getDate()).padStart(2, '0');
|
||||||
|
el.value = d.getFullYear() + '-' + m + '-' + day;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Inicjalizacja tabeli
|
||||||
|
var table = $('#products').DataTable();
|
||||||
table.destroy();
|
table.destroy();
|
||||||
|
|
||||||
new DataTable( '#products', {
|
new DataTable('#products', {
|
||||||
ajax: {
|
ajax: {
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/products/get_product_history_table/client_id=' + client_id + '&product_id=' + product_id,
|
url: '/products/get_product_history_table/client_id=' + client_id + '&product_id=' + product_id,
|
||||||
@@ -49,79 +79,40 @@
|
|||||||
processing: true,
|
processing: true,
|
||||||
serverSide: true,
|
serverSide: true,
|
||||||
searching: false,
|
searching: false,
|
||||||
columns: [{
|
columns: [
|
||||||
width: '100px',
|
{ width: '100px', orderable: false },
|
||||||
orderable: false
|
{ width: '100px', name: 'impressions' },
|
||||||
},
|
{ width: '100px', name: 'clicks' },
|
||||||
{
|
{ width: '100px', name: 'ctr', className: "dt-type-numeric" },
|
||||||
width: '100px',
|
{ width: '100px', name: 'cost', className: "dt-type-numeric" },
|
||||||
name: 'impressions'
|
{ width: '100px', name: 'conversions' },
|
||||||
},
|
{ width: '175px', name: 'conversions_value', className: "dt-type-numeric" },
|
||||||
{
|
{ width: '100px', name: 'roas', className: "dt-type-numeric", orderable: false },
|
||||||
width: '100px',
|
{ width: '100px', name: 'date_add' },
|
||||||
name: 'clicks'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
width: '100px',
|
|
||||||
name: 'ctr',
|
|
||||||
className: "dt-type-numeric"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
width: '100px',
|
|
||||||
name: 'cost',
|
|
||||||
className: "dt-type-numeric"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
width: '100px',
|
|
||||||
name: 'conversions'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
width: '175px',
|
|
||||||
name: 'conversions_value',
|
|
||||||
className: "dt-type-numeric"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
width: '100px',
|
|
||||||
name: 'roas',
|
|
||||||
className: "dt-type-numeric",
|
|
||||||
orderable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
width: '100px',
|
|
||||||
name: 'date_add'
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
order: [
|
order: [[0, false],[8, 'desc']]
|
||||||
[ 0, false],
|
|
||||||
[ 8, 'desc']
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// WYKRES
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/products/get_product_history_table_chart/',
|
url: '/products/get_product_history_table_chart/',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: {
|
data: { client_id: client_id, product_id: product_id },
|
||||||
client_id: client_id,
|
|
||||||
product_id: product_id,
|
|
||||||
},
|
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
const parsedData = JSON.parse(response);
|
const parsedData = JSON.parse(response);
|
||||||
|
|
||||||
let plotLines = [];
|
let plotLines = [];
|
||||||
|
(parsedData.comments || []).forEach(function(comment) {
|
||||||
parsedData.comments.forEach(function(comment) {
|
|
||||||
plotLines.push({
|
plotLines.push({
|
||||||
color: '#333333',
|
color: '#333333',
|
||||||
width: 1,
|
width: 1,
|
||||||
value: parsedData.dates.indexOf(comment.date_add.split(' ')[0]),
|
value: parsedData.dates.indexOf((comment.date_add || '').split(' ')[0]),
|
||||||
dashStyle: 'Solid',
|
dashStyle: 'Solid',
|
||||||
label: {
|
label: {
|
||||||
text: comment.comment,
|
text: comment.comment, // trzyma przy lewej krawędzi linii
|
||||||
|
rotation: 0,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
style: {
|
style: { color: '#333333', fontSize: '14px' }
|
||||||
color: '#333333',
|
|
||||||
fontSize: '14px'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
zIndex: 5
|
zIndex: 5
|
||||||
});
|
});
|
||||||
@@ -130,8 +121,6 @@
|
|||||||
const chart = Highcharts.chart('container', {
|
const chart = Highcharts.chart('container', {
|
||||||
title: { text: `` },
|
title: { text: `` },
|
||||||
subtitle: { text: `` },
|
subtitle: { text: `` },
|
||||||
|
|
||||||
// (możesz zostawić lub usunąć warunkowy blok yAxis z PHP — ten kod zadziała niezależnie)
|
|
||||||
xAxis: {
|
xAxis: {
|
||||||
categories: parsedData.dates,
|
categories: parsedData.dates,
|
||||||
labels: {
|
labels: {
|
||||||
@@ -156,25 +145,56 @@
|
|||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
itemStyle: { fontSize: '14px' }
|
itemStyle: { fontSize: '14px' }
|
||||||
},
|
},
|
||||||
plotOptions: {
|
plotOptions: { series: { label: { connectorAllowed: false }, pointStart: 0 } },
|
||||||
series: { label: { connectorAllowed: false }, pointStart: 0 }
|
|
||||||
},
|
|
||||||
series: parsedData.chart_data,
|
series: parsedData.chart_data,
|
||||||
tooltip: { style: { fontSize: '14px' } }
|
tooltip: { style: { fontSize: '14px' } }
|
||||||
});
|
});
|
||||||
|
|
||||||
// >>> DODAJ TO PO UTWORZENIU WYKRESU <<<
|
chart.xAxis[0].update({
|
||||||
<?php if ($this->min_roas): ?>
|
plotLines: (chart.xAxis[0].options.plotLines || []).map(function(pl) {
|
||||||
|
return Highcharts.merge(pl, { label: { text: '' } });
|
||||||
|
})
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// 2) Dodaj „niewidzialne” markery do hovera
|
||||||
|
var points = (parsedData.comments || []).map(function(c) {
|
||||||
|
var idx = parsedData.dates.indexOf((c.date_add || '').split(' ')[0]);
|
||||||
|
return { x: idx, y: 0, comment: c.comment };
|
||||||
|
});
|
||||||
|
|
||||||
|
chart.addSeries({
|
||||||
|
type: 'scatter',
|
||||||
|
name: 'Komentarz:',
|
||||||
|
data: points,
|
||||||
|
yAxis: 0,
|
||||||
|
tooltip: {
|
||||||
|
pointFormatter: function () {
|
||||||
|
return '<span style="font-size: 12px;">' + (this.comment || '') + '</span>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
marker: {
|
||||||
|
enabled: true,
|
||||||
|
radius: 4,
|
||||||
|
lineWidth: 0,
|
||||||
|
fillOpacity: 0 // marker „niewidoczny”
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
hover: { enabled: true, halo: { size: 5 } }
|
||||||
|
},
|
||||||
|
enableMouseTracking: true
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
chart.redraw();
|
||||||
|
|
||||||
|
// MIN ROAS linia + dopasowanie osi
|
||||||
|
<?php if ($this->min_roas): ?>
|
||||||
(function() {
|
(function() {
|
||||||
var limitVal = Number(<?= json_encode($this->min_roas) ?>);
|
var limitVal = Number(<?= json_encode($this->min_roas) ?>);
|
||||||
|
|
||||||
var roasSeries = chart.series.find(function(s) {
|
var roasSeries = chart.series.find(function(s) {
|
||||||
return (s.name || '').toLowerCase() === 'roas';
|
return (s.name || '').toLowerCase() === 'roas';
|
||||||
});
|
});
|
||||||
|
|
||||||
var targetAxis = roasSeries ? roasSeries.yAxis : chart.yAxis[0];
|
var targetAxis = roasSeries ? roasSeries.yAxis : chart.yAxis[0];
|
||||||
|
|
||||||
// dodanie linii
|
|
||||||
targetAxis.addPlotLine({
|
targetAxis.addPlotLine({
|
||||||
id: 'min-roas-line',
|
id: 'min-roas-line',
|
||||||
color: 'red',
|
color: 'red',
|
||||||
@@ -195,20 +215,15 @@
|
|||||||
|
|
||||||
var min = Math.min(e.dataMin, val);
|
var min = Math.min(e.dataMin, val);
|
||||||
var max = Math.max(e.dataMax, val);
|
var max = Math.max(e.dataMax, val);
|
||||||
|
|
||||||
var span = (max - min) || 1;
|
var span = (max - min) || 1;
|
||||||
var pad = span * 0.05;
|
var pad = span * 0.05;
|
||||||
|
|
||||||
var newMin = min - pad;
|
var newMin = min - pad;
|
||||||
var newMax = max + pad;
|
var newMax = max + pad;
|
||||||
|
|
||||||
// uniknij niepotrzebnych setExtremes
|
|
||||||
if (newMin !== e.min || newMax !== e.max) {
|
if (newMin !== e.min || newMax !== e.max) {
|
||||||
axis.setExtremes(newMin, newMax); // domyślnie robi redraw
|
axis.setExtremes(newMin, newMax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1) po załadowaniu wykresu (jeśli już załadowany – od razu)
|
|
||||||
if (chart.hasLoaded) {
|
if (chart.hasLoaded) {
|
||||||
adjustAxisToIncludeValue(targetAxis, limitVal);
|
adjustAxisToIncludeValue(targetAxis, limitVal);
|
||||||
} else {
|
} else {
|
||||||
@@ -217,22 +232,54 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) przy show/hide serii (klik w legendzie)
|
|
||||||
chart.series.forEach(function (s) {
|
chart.series.forEach(function (s) {
|
||||||
Highcharts.addEvent(s, 'show', function () {
|
Highcharts.addEvent(s, 'show', function () { adjustAxisToIncludeValue(targetAxis, limitVal); });
|
||||||
adjustAxisToIncludeValue(targetAxis, limitVal);
|
Highcharts.addEvent(s, 'hide', function () { adjustAxisToIncludeValue(targetAxis, limitVal); });
|
||||||
});
|
|
||||||
Highcharts.addEvent(s, 'hide', function () {
|
|
||||||
adjustAxisToIncludeValue(targetAxis, limitVal);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
},
|
},
|
||||||
error: function (jqXHR, textStatus, errorThrown) {
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
console.error('Error AJAX:', textStatus, errorThrown);
|
console.error('Error AJAX:', textStatus, errorThrown);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
|
||||||
</script>
|
// OBSŁUGA FORMULARZA – zapis komentarza i odświeżenie strony
|
||||||
|
$('#product-comment-form').on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var $btn = $('#save_comment');
|
||||||
|
var dateStr = $.trim($('#comment_date').val());
|
||||||
|
var comment = $.trim($('#comment_text').val());
|
||||||
|
|
||||||
|
if (!dateStr) { alert('Wybierz datę.'); return; }
|
||||||
|
if (!comment) { alert('Wpisz komentarz.'); return; }
|
||||||
|
|
||||||
|
$btn.prop('disabled', true).text('Zapisywanie...');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/products/comment_add/',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
client_id: client_id,
|
||||||
|
product_id: product_id,
|
||||||
|
date: dateStr, // oczekiwany format: YYYY-MM-DD
|
||||||
|
comment: comment
|
||||||
|
},
|
||||||
|
success: function(res) {
|
||||||
|
res = JSON.parse(res);
|
||||||
|
if (res.status === 'ok') {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Nie udało się zapisać komentarza. Spróbuj ponownie.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
|
console.error('Błąd zapisu komentarza:', textStatus, errorThrown);
|
||||||
|
alert('Nie udało się zapisać komentarza. Spróbuj ponownie.');
|
||||||
|
$btn.prop('disabled', false).text('Zapisz komentarz');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user