fixed lookup options

This commit is contained in:
2026-10-29 17:22:27 +01:00
parent eebfee4092
commit edafcb357f
4 changed files with 209 additions and 6 deletions
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class WidenLubricationTypeOnWorkSheetMescole extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function up(): void
{
$this->table('work_sheet_mescole')
->changeColumn('lubrication_type', 'string', [
'limit' => 60,
'null' => true,
'default' => null,
'comment' => 'Valore da ws_lookup_options (category lubrication_type)',
])
->update();
}
public function down(): void
{
// i valori non previsti dal vecchio ENUM vengono azzerati, altrimenti il ripristino fallisce
$this->execute("UPDATE work_sheet_mescole SET lubrication_type = NULL WHERE lubrication_type NOT IN ('S','G','N')");
$this->table('work_sheet_mescole')
->changeColumn('lubrication_type', 'enum', [
'values' => ['S', 'G', 'N'],
'null' => true,
'default' => null,
])
->update();
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
use Phinx\Db\Adapter\MysqlAdapter;
final class AddDifficoltaToMatrice extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('matrice')
->addColumn('difficolta', 'integer', [
'limit' => MysqlAdapter::INT_TINY,
'signed' => false,
'null' => true,
'default' => null,
'after' => 'cliente',
'comment' => 'Difficoltà 1 (facile) - 10 (difficile), NULL = non indicata',
])
->addIndex(['difficolta'], ['name' => 'idx_matrice_difficolta'])
->update();
}
}
+115 -2
View File
@@ -46,6 +46,48 @@ function revisionLabel($rev)
return $rev !== '' ? $rev : '0'; return $rev !== '' ? $rev : '0';
} }
/**
* DIFFICOLTÀ MATRICE (1 = più facile, 10 = più difficile)
* Per aggiungere un'etichetta basta una riga qui (es. 8 => 'Molto difficile').
*/
const DIFF_LABELS = [1 => 'Facile', 5 => 'Media', 10 => 'Difficile'];
// fasce usate dal filtro in tabella
const DIFF_BANDS = [
'facile' => ['label' => 'Facile (1–3)', 'min' => 1, 'max' => 3],
'media' => ['label' => 'Media (4–7)', 'min' => 4, 'max' => 7],
'difficile' => ['label' => 'Difficile (8–10)', 'min' => 8, 'max' => 10],
];
function diffValue($v)
{
$n = (int)$v;
return ($n >= 1 && $n <= 10) ? $n : null;
}
/** testo: "5 · Media", "3", "" */
function diffText($v)
{
$n = diffValue($v);
if ($n === null) return '';
return isset(DIFF_LABELS[$n]) ? $n . ' · ' . DIFF_LABELS[$n] : (string)$n;
}
/** colore dal verde (1) al rosso (10) */
function diffStyle($v)
{
$n = diffValue($v);
if ($n === null) return '';
$hue = (int)round(120 * (10 - $n) / 9);
return "background:hsl($hue,75%,90%);color:hsl($hue,70%,26%);border-color:hsl($hue,55%,68%);";
}
function diffBadge($v)
{
$n = diffValue($v);
if ($n === null) return "<span class='diff-badge diff-none'>—</span>";
return "<span class='diff-badge' style='" . diffStyle($n) . "'>" . h(diffText($n)) . "</span>";
}
?> ?>
<!doctype html> <!doctype html>
<html lang="it"> <html lang="it">
@@ -489,6 +531,29 @@ function revisionLabel($rev)
font-size: .82rem; font-size: .82rem;
} }
.diff-badge {
display: inline-block;
min-width: 34px;
padding: 3px 10px;
border-radius: 999px;
border: 1px solid transparent;
font-weight: 600;
font-size: .85rem;
white-space: nowrap;
}
.diff-badge.diff-none {
color: #adb5bd;
background: #f8f9fa;
border-color: #e9ecef;
}
#diffFilter {
display: inline-block;
width: auto;
margin-left: 10px;
}
.worksheet-counter-badge { .worksheet-counter-badge {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -714,6 +779,7 @@ function revisionLabel($rev)
<th>Foto</th> <th>Foto</th>
<th>Nome</th> <th>Nome</th>
<th>Cliente</th> <th>Cliente</th>
<th>Difficoltà</th>
<th>Linee</th> <th>Linee</th>
<th>Fogli</th> <th>Fogli</th>
<th>Azioni</th> <th>Azioni</th>
@@ -760,7 +826,7 @@ function revisionLabel($rev)
"); ");
if ($stmt->rowCount() === 0) { if ($stmt->rowCount() === 0) {
echo "<tr><td colspan='6' class='text-muted'>Nessuna matrice presente</td></tr>"; echo "<tr><td colspan='7' class='text-muted'>Nessuna matrice presente</td></tr>";
} else { } else {
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$dataIT = formatDateIT($row['data_produzione']); $dataIT = formatDateIT($row['data_produzione']);
@@ -802,6 +868,11 @@ function revisionLabel($rev)
. htmlspecialchars($row['cliente']) . htmlspecialchars($row['cliente'])
. "</td>"; . "</td>";
$diff = diffValue($row['difficolta'] ?? null);
echo "<td class='diff-cell' data-diff='" . ($diff ?? '') . "' data-order='" . ($diff ?? 0) . "'>"
. diffBadge($diff)
. "</td>";
$lineeTxt = $row['linee_associate'] ?? '—'; $lineeTxt = $row['linee_associate'] ?? '—';
$mescoleTxt = $row['mescole_associate'] ?? ''; $mescoleTxt = $row['mescole_associate'] ?? '';
$mescoleCount = (int)($row['mescole_count'] ?? 0); $mescoleCount = (int)($row['mescole_count'] ?? 0);
@@ -849,6 +920,7 @@ function revisionLabel($rev)
data-nome='" . htmlspecialchars($row['nome'], ENT_QUOTES) . "' data-nome='" . htmlspecialchars($row['nome'], ENT_QUOTES) . "'
data-cliente='" . htmlspecialchars($row['cliente'], ENT_QUOTES) . "' data-cliente='" . htmlspecialchars($row['cliente'], ENT_QUOTES) . "'
data-data='{$dataIT}' data-data='{$dataIT}'
data-difficolta='" . (diffValue($row['difficolta'] ?? null) ?? '') . "'
data-photo='" . htmlspecialchars($hasPhoto ? $thumb : '', ENT_QUOTES) . "' data-photo='" . htmlspecialchars($hasPhoto ? $thumb : '', ENT_QUOTES) . "'
data-bs-toggle='tooltip' data-bs-title='Modifica'> data-bs-toggle='tooltip' data-bs-title='Modifica'>
<i class='fa-solid fa-pen-to-square'></i> <i class='fa-solid fa-pen-to-square'></i>
@@ -929,6 +1001,17 @@ function revisionLabel($rev)
<input type="text" class="form-control" id="clienteMatrice"> <input type="text" class="form-control" id="clienteMatrice">
</div> </div>
<div class="mb-3">
<label class="fw-semibold">Difficoltà</label>
<select class="form-select" id="difficoltaMatrice">
<option value="">— Non indicata —</option>
<?php for ($i = 1; $i <= 10; $i++): ?>
<option value="<?= $i ?>" style="<?= h(diffStyle($i)) ?>"><?= h(diffText($i)) ?></option>
<?php endfor; ?>
</select>
<div class="form-text">1 = più facile, 10 = più difficile</div>
</div>
<div class="mb-3"> <div class="mb-3">
<label class="fw-semibold">Data</label> <label class="fw-semibold">Data</label>
<input type="text" class="form-control" id="dataMatrice" placeholder="dd/mm/yyyy"> <input type="text" class="form-control" id="dataMatrice" placeholder="dd/mm/yyyy">
@@ -1551,6 +1634,9 @@ function revisionLabel($rev)
if (!old) return; if (!old) return;
old.innerHTML = td.innerHTML; old.innerHTML = td.innerHTML;
if (td.hasAttribute('title')) old.setAttribute('title', td.getAttribute('title')); if (td.hasAttribute('title')) old.setAttribute('title', td.getAttribute('title'));
['data-diff', 'data-order'].forEach(a => {
if (td.hasAttribute(a)) old.setAttribute(a, td.getAttribute(a));
});
}); });
this.invalidate('dom'); this.invalidate('dom');
flashRow(tr); flashRow(tr);
@@ -1592,7 +1678,10 @@ function revisionLabel($rev)
return data; return data;
} }
}, { }, {
targets: 5, targets: 3,
searchable: false
}, {
targets: 6,
orderable: false, orderable: false,
searchable: false searchable: false
}], }],
@@ -1610,6 +1699,28 @@ function revisionLabel($rev)
.attr('placeholder', 'Nome matrice, cliente…') .attr('placeholder', 'Nome matrice, cliente…')
.addClass('form-control'); .addClass('form-control');
// ---- filtro difficoltà ----
const DIFF_BANDS = <?= json_encode(DIFF_BANDS, JSON_UNESCAPED_UNICODE) ?>;
const $diffFilter = $('<select id="diffFilter" class="form-select form-select-sm"></select>')
.append('<option value="">Difficoltà: tutte</option>');
Object.keys(DIFF_BANDS).forEach(k => $diffFilter.append($('<option>').val(k).text(DIFF_BANDS[k].label)));
$diffFilter.append('<option value="none">Non indicata</option>');
$('#tabellaMatrici_filter').append($diffFilter);
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
if (settings.nTable.id !== 'tabellaMatrici') return true;
const f = $diffFilter.val();
if (!f) return true;
const tr = settings.aoData[dataIndex].nTr;
const td = tr && tr.querySelector('td.diff-cell');
if (!td) return false;
const n = parseInt(td.getAttribute('data-diff') || '0', 10);
if (f === 'none') return !n;
const b = DIFF_BANDS[f];
return n >= b.min && n <= b.max;
});
$diffFilter.on('change', () => $('#tabellaMatrici').DataTable().draw());
function resetFotoMatrice(photoUrl) { function resetFotoMatrice(photoUrl) {
$("#fotoMatrice").val(''); $("#fotoMatrice").val('');
$("#removeFotoMatrice").val('0'); $("#removeFotoMatrice").val('0');
@@ -1627,6 +1738,7 @@ function revisionLabel($rev)
$("#nomeMatrice").val($(this).data("nome")); $("#nomeMatrice").val($(this).data("nome"));
$("#clienteMatrice").val($(this).data("cliente")); $("#clienteMatrice").val($(this).data("cliente"));
$("#dataMatrice").val($(this).data("data")); $("#dataMatrice").val($(this).data("data"));
$("#difficoltaMatrice").val(String($(this).attr("data-difficolta") || ''));
resetFotoMatrice($(this).data("photo") || ""); resetFotoMatrice($(this).data("photo") || "");
bootstrap.Modal.getOrCreateInstance(document.getElementById('addMatriceModal')).show(); bootstrap.Modal.getOrCreateInstance(document.getElementById('addMatriceModal')).show();
}); });
@@ -1669,6 +1781,7 @@ function revisionLabel($rev)
formData.append("nome", nome); formData.append("nome", nome);
formData.append("cliente", cliente); formData.append("cliente", cliente);
formData.append("data", dataSQL); formData.append("data", dataSQL);
formData.append("difficolta", $("#difficoltaMatrice").val());
formData.append("remove_photo", $("#removeFotoMatrice").val()); formData.append("remove_photo", $("#removeFotoMatrice").val());
const fotoFile = $("#fotoMatrice")[0].files[0]; const fotoFile = $("#fotoMatrice")[0].files[0];
+14 -4
View File
@@ -17,6 +17,7 @@ $id = (int)($_POST['id'] ?? 0);
$nome = trim($_POST['nome'] ?? ''); $nome = trim($_POST['nome'] ?? '');
$cliente = trim($_POST['cliente'] ?? ''); $cliente = trim($_POST['cliente'] ?? '');
$data = trim($_POST['data'] ?? ''); $data = trim($_POST['data'] ?? '');
$difficolta = trim($_POST['difficolta'] ?? '');
$removePhoto = ($_POST['remove_photo'] ?? '0') === '1'; $removePhoto = ($_POST['remove_photo'] ?? '0') === '1';
if ($nome === '') { if ($nome === '') {
@@ -26,6 +27,15 @@ if ($nome === '') {
$data = ($data !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $data)) ? $data : null; $data = ($data !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $data)) ? $data : null;
$cliente = $cliente !== '' ? $cliente : null; $cliente = $cliente !== '' ? $cliente : null;
// difficoltà: vuota = non indicata, altrimenti intero 1..10
if ($difficolta === '') {
$difficolta = null;
} elseif (ctype_digit($difficolta) && (int)$difficolta >= 1 && (int)$difficolta <= 10) {
$difficolta = (int)$difficolta;
} else {
jsonOut(false, 'Difficoltà non valida (valori ammessi: 1–10)');
}
$photoDir = __DIR__ . '/photos/matrici/'; $photoDir = __DIR__ . '/photos/matrici/';
if (!is_dir($photoDir)) { if (!is_dir($photoDir)) {
mkdir($photoDir, 0775, true); mkdir($photoDir, 0775, true);
@@ -65,11 +75,11 @@ try {
} }
$oldPhoto = $row['photo']; $oldPhoto = $row['photo'];
$st = $pdo->prepare("UPDATE matrice SET nome = ?, cliente = ?, data_produzione = ? WHERE id = ?"); $st = $pdo->prepare("UPDATE matrice SET nome = ?, cliente = ?, data_produzione = ?, difficolta = ? WHERE id = ?");
$st->execute([$nome, $cliente, $data, $id]); $st->execute([$nome, $cliente, $data, $difficolta, $id]);
} else { } else {
$st = $pdo->prepare("INSERT INTO matrice (nome, cliente, data_produzione) VALUES (?, ?, ?)"); $st = $pdo->prepare("INSERT INTO matrice (nome, cliente, data_produzione, difficolta) VALUES (?, ?, ?, ?)");
$st->execute([$nome, $cliente, $data]); $st->execute([$nome, $cliente, $data, $difficolta]);
$id = (int)$pdo->lastInsertId(); $id = (int)$pdo->lastInsertId();
} }