424 lines
18 KiB
PHP
424 lines
18 KiB
PHP
<?php
|
|
include('include/headscript.php');
|
|
require_once(__DIR__ . '/class/db-functions.php'); // usa la tua classe PDO
|
|
|
|
$db = DBHandlerSelect::getInstance();
|
|
$pdo = $db->getConnection();
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Imported Data Management</title>
|
|
<?php include('cssinclude.php'); ?>
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">
|
|
|
|
<style>
|
|
.editable {
|
|
cursor: pointer;
|
|
background-color: #fff8e1;
|
|
}
|
|
|
|
.action-btn {
|
|
padding: 4px 8px;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
td.editable:hover {
|
|
background-color: #fff5cc;
|
|
cursor: text;
|
|
}
|
|
|
|
td.modified {
|
|
background-color: #ff9c9cff !important;
|
|
/* evidenzia celle modificate */
|
|
}
|
|
|
|
td.noedit {
|
|
background-color: #f8f9fa;
|
|
color: #888;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<div class="dashboard-main-wrapper wrapper">
|
|
<?php include('include/topbar.php'); ?>
|
|
|
|
<div class="dashboard-body">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div class="d-flex flex-wrap justify-content-between align-items-center mb-3">
|
|
<h4 class="mb-0">Imported Data</h4>
|
|
<div class="d-flex align-items-center gap-2">
|
|
<label for="clientFilter" class="form-label mb-0 me-2">Filter by Client:</label>
|
|
<select id="clientFilter" class="form-select form-select-sm" style="width: 220px;">
|
|
<option value="">All Clients</option>
|
|
<?php
|
|
// carichiamo i clienti dal DB
|
|
$clients = $pdo->query("SELECT idclient, client_name FROM clients ORDER BY client_name")->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($clients as $cl) {
|
|
echo '<option value="' . htmlspecialchars($cl['idclient']) . '">' . htmlspecialchars($cl['client_name']) . '</option>';
|
|
}
|
|
?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<div>
|
|
<button id="updatePricesBtn" class="btn btn-warning btn-sm" style="display:none;">
|
|
<i class="fas fa-sync-alt"></i> Aggiorna Prezzi
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table id="importTable" class="table table-striped table-bordered w-100">
|
|
|
|
<thead>
|
|
<tr>
|
|
<th></th> <!-- Checkbox column -->
|
|
<th>ID</th>
|
|
<th>Collection</th>
|
|
<th>Category</th>
|
|
<th>Model</th>
|
|
<th>Model Description</th>
|
|
<th>Mod.Code</th>
|
|
<th>Description</th>
|
|
<th>Finish.Code</th>
|
|
<th>Finishing Description</th>
|
|
<th>Available Qty</th>
|
|
<th>WH</th>
|
|
<th>Price</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
|
|
<?php include('jsinclude.php'); ?>
|
|
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
let table = $('#importTable').DataTable({
|
|
ajax: {
|
|
url: 'import_list_data.php',
|
|
dataSrc: ''
|
|
},
|
|
columns: [{
|
|
data: null,
|
|
orderable: false,
|
|
searchable: false,
|
|
className: 'text-center',
|
|
render: function() {
|
|
return '<input type="checkbox" class="row-check" />';
|
|
}
|
|
},
|
|
{
|
|
data: 'id'
|
|
},
|
|
{
|
|
data: 'collection',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'category',
|
|
className: 'noedit text-muted'
|
|
},
|
|
{
|
|
data: 'model',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'model_description',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'mod_code',
|
|
className: 'text-muted'
|
|
},
|
|
{
|
|
data: 'description',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'finish_code',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'finishing_description',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'available_qty',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'wh',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: 'price',
|
|
className: 'editable'
|
|
},
|
|
{
|
|
data: null,
|
|
orderable: false,
|
|
render: function(data, type, row) {
|
|
return `
|
|
<button class="btn btn-success btn-sm action-btn save-row" data-id="${row.id}">
|
|
<i class="fas fa-save"></i>
|
|
</button>
|
|
<button class="btn btn-danger btn-sm action-btn delete-row" data-id="${row.id}">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
`;
|
|
}
|
|
}
|
|
],
|
|
pageLength: 25,
|
|
order: [
|
|
[1, 'desc']
|
|
],
|
|
responsive: true,
|
|
autoWidth: false
|
|
});
|
|
|
|
|
|
// === Filtro per Client ===
|
|
$('#clientFilter').on('change', function() {
|
|
const selectedClient = $(this).val();
|
|
|
|
// Ricarica i dati passando il parametro idclient
|
|
table.ajax.url('import_list_data.php' + (selectedClient ? '?idclient=' + selectedClient : '')).load();
|
|
});
|
|
|
|
|
|
// === Inline Editing ===
|
|
$('#importTable tbody').on('click', 'td.editable', function() {
|
|
const cell = table.cell(this);
|
|
const rowData = table.row(cell.index().row).data();
|
|
const colName = table.column(cell.index().column).dataSrc();
|
|
const originalValue = rowData[colName] ?? '';
|
|
|
|
// Evita doppia apertura
|
|
if ($(this).find('input').length > 0) return;
|
|
|
|
const input = $('<input type="text" class="form-control form-control-sm"/>')
|
|
.val(originalValue)
|
|
.css({
|
|
'min-width': '120px',
|
|
'height': '24px',
|
|
'padding': '0 4px'
|
|
});
|
|
|
|
$(this).html(input);
|
|
input.focus();
|
|
|
|
// Gestione conferma o uscita
|
|
input.on('blur keydown', function(e) {
|
|
if (e.type === 'blur' || e.key === 'Enter') {
|
|
const newValue = $(this).val();
|
|
// Aggiorna in memoria e interfaccia
|
|
rowData[colName] = newValue;
|
|
table.row(cell.index().row).data(rowData).draw(false);
|
|
|
|
const td = $(table.cell(cell.index()).node());
|
|
if (newValue !== originalValue) {
|
|
td.addClass('modified'); // evidenzia modificato
|
|
} else {
|
|
td.removeClass('modified');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// === Salvataggio singola riga ===
|
|
$('#importTable').on('click', '.save-row', function() {
|
|
const rowData = table.row($(this).closest('tr')).data();
|
|
$.ajax({
|
|
url: 'import_list_save.php',
|
|
type: 'POST',
|
|
data: {
|
|
row: JSON.stringify(rowData)
|
|
},
|
|
success: function(res) {
|
|
Swal.close();
|
|
|
|
// Se il server restituisce già JSON, non serve JSON.parse()
|
|
let json = (typeof res === 'object') ? res : null;
|
|
if (!json) {
|
|
try {
|
|
json = JSON.parse(res);
|
|
} catch (e) {
|
|
console.error("Invalid JSON from server:", res);
|
|
Swal.fire('Errore', 'Risposta non valida dal server.', 'error');
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (json.status === 'ok') {
|
|
Swal.fire({
|
|
title: 'Successo',
|
|
text: `Aggiornati ${json.updated} prezzi.`,
|
|
icon: 'success',
|
|
timer: 2000,
|
|
showConfirmButton: false
|
|
});
|
|
table.ajax.reload(null, false); // 🔁 aggiorna tabella
|
|
} else {
|
|
console.error("Errore backend:", json);
|
|
Swal.fire('Errore', json.message || 'Errore sconosciuto.', 'error');
|
|
}
|
|
},
|
|
error: function(xhr, status, err) {
|
|
Swal.fire('Errore', 'Errore di rete o server non raggiungibile.', 'error');
|
|
console.error("AJAX error:", status, err, xhr.responseText);
|
|
}
|
|
|
|
});
|
|
});
|
|
|
|
// === Eliminazione con conferma ===
|
|
$('#importTable').on('click', '.delete-row', function() {
|
|
const id = $(this).data('id');
|
|
Swal.fire({
|
|
title: 'Are you sure?',
|
|
text: 'This record will be permanently deleted.',
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Yes, delete it',
|
|
cancelButtonText: 'Cancel'
|
|
}).then(result => {
|
|
if (result.isConfirmed) {
|
|
$.ajax({
|
|
url: 'import_list_delete.php',
|
|
type: 'POST',
|
|
data: {
|
|
id: id
|
|
},
|
|
success: function(res) {
|
|
let json;
|
|
try {
|
|
json = JSON.parse(res);
|
|
} catch (e) {
|
|
Swal.fire('Error', res, 'error');
|
|
return;
|
|
}
|
|
if (json.status === 'ok') {
|
|
Swal.fire('Deleted', 'Row removed successfully.', 'success');
|
|
table.ajax.reload(null, false);
|
|
} else {
|
|
Swal.fire('Error', json.message, 'error');
|
|
}
|
|
},
|
|
error: function() {
|
|
Swal.fire('Error', 'Request failed.', 'error');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// === Gestione selezione righe e pulsante Aggiorna Prezzi ===
|
|
$('#importTable').on('change', '.row-check', function() {
|
|
const checkedCount = $('#importTable .row-check:checked').length;
|
|
$('#updatePricesBtn').toggle(checkedCount > 0);
|
|
});
|
|
|
|
// === Aggiornamento prezzi con ChatPDF ===
|
|
$('#updatePricesBtn').on('click', function() {
|
|
const selectedRows = [];
|
|
|
|
$('#importTable .row-check:checked').each(function() {
|
|
const row = table.row($(this).closest('tr')).data();
|
|
if (row) selectedRows.push(row);
|
|
});
|
|
|
|
if (selectedRows.length === 0) {
|
|
Swal.fire('Notice', 'Seleziona almeno una riga.', 'info');
|
|
return;
|
|
}
|
|
|
|
const clientId = $('#clientFilter').val();
|
|
if (!clientId) {
|
|
Swal.fire('Notice', 'Seleziona prima un cliente.', 'info');
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: 'Aggiornare i prezzi?',
|
|
text: `Verranno interrogati i prezzi per ${selectedRows.length} prodotti.`,
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Procedi',
|
|
cancelButtonText: 'Annulla'
|
|
}).then(result => {
|
|
if (result.isConfirmed) {
|
|
Swal.fire({
|
|
title: 'Aggiornamento in corso...',
|
|
allowOutsideClick: false,
|
|
didOpen: () => Swal.showLoading()
|
|
});
|
|
|
|
$.ajax({
|
|
url: 'update_prices_chatpdf.php',
|
|
type: 'POST',
|
|
data: {
|
|
rows: JSON.stringify(selectedRows),
|
|
idclient: clientId
|
|
},
|
|
success: function(res) {
|
|
Swal.close();
|
|
|
|
// Se il server ha già restituito un oggetto JSON, usiamolo direttamente
|
|
let json = (typeof res === "object") ? res : null;
|
|
|
|
// Se invece è una stringa JSON, parse
|
|
if (!json) {
|
|
try {
|
|
json = JSON.parse(res);
|
|
} catch (e) {
|
|
console.error("JSON parse error:", res);
|
|
Swal.fire('Errore', 'Risposta non valida dal server.', 'error');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Ora siamo sicuri che json è un oggetto valido
|
|
if (json.status === 'ok') {
|
|
Swal.fire('Successo', `Aggiornati ${json.updated} prezzi.`, 'success');
|
|
table.ajax.reload(null, false);
|
|
} else {
|
|
Swal.fire('Errore', json.message || 'Errore sconosciuto.', 'error');
|
|
}
|
|
},
|
|
|
|
error: function() {
|
|
Swal.fire('Errore', 'Aggiornamento fallito.', 'error');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
});
|
|
</script>
|
|
</div> <!-- end wrapper -->
|
|
</body>
|
|
|
|
</html>
|