loopkup, foglio di lavoro
This commit is contained in:
parent
31f22b4d92
commit
22e5b90fe4
643
public/userarea/lookup_values.php
Normal file
643
public/userarea/lookup_values.php
Normal file
@ -0,0 +1,643 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include('include/headscript.php');
|
||||
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
|
||||
/**
|
||||
* ws_lookup_options manager page
|
||||
* Table expected:
|
||||
* - id (AI)
|
||||
* - category (varchar)
|
||||
* - value (varchar)
|
||||
* - label (varchar)
|
||||
* - sort_order (int)
|
||||
* - is_default (tinyint 0/1)
|
||||
* - is_active (tinyint 0/1)
|
||||
*/
|
||||
|
||||
// AJAX HANDLERS
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
try {
|
||||
|
||||
if ($action === 'add') {
|
||||
$category = trim($_POST['category'] ?? '');
|
||||
$value = trim($_POST['value'] ?? '');
|
||||
$label = trim($_POST['label'] ?? '');
|
||||
$sort_order = (int)($_POST['sort_order'] ?? 100);
|
||||
$is_default = (int)($_POST['is_default'] ?? 0) ? 1 : 0;
|
||||
$is_active = (int)($_POST['is_active'] ?? 1) ? 1 : 0;
|
||||
|
||||
if ($category === '' || $value === '' || $label === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Compila category, value e label']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// If set as default, unset other defaults in same category (simple & reliable)
|
||||
if ($is_default === 1) {
|
||||
$stmt = $pdo->prepare("UPDATE ws_lookup_options SET is_default = 0 WHERE category = ?");
|
||||
$stmt->execute([$category]);
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO ws_lookup_options
|
||||
(category, value, label, sort_order, is_default, is_active)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
$stmt->execute([$category, $value, $label, $sort_order, $is_default, $is_active]);
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action === 'edit') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$category = trim($_POST['category'] ?? '');
|
||||
$value = trim($_POST['value'] ?? '');
|
||||
$label = trim($_POST['label'] ?? '');
|
||||
$sort_order = (int)($_POST['sort_order'] ?? 100);
|
||||
$is_default = (int)($_POST['is_default'] ?? 0) ? 1 : 0;
|
||||
$is_active = (int)($_POST['is_active'] ?? 1) ? 1 : 0;
|
||||
|
||||
if ($id <= 0 || $category === '' || $value === '' || $label === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Dati non validi']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// If set as default, unset other defaults in same category (excluding current)
|
||||
if ($is_default === 1) {
|
||||
$stmt = $pdo->prepare("UPDATE ws_lookup_options SET is_default = 0 WHERE category = ? AND id <> ?");
|
||||
$stmt->execute([$category, $id]);
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE ws_lookup_options SET
|
||||
category = ?,
|
||||
value = ?,
|
||||
label = ?,
|
||||
sort_order = ?,
|
||||
is_default = ?,
|
||||
is_active = ?
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt->execute([$category, $value, $label, $sort_order, $is_default, $is_active, $id]);
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action === 'delete') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'ID non valido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM ws_lookup_options WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Categories list (static for now, easy to extend)
|
||||
$categories = [
|
||||
'marking' => 'Marchiatura',
|
||||
'lubrication_type' => 'Lubrificazione',
|
||||
'control_frequency_cut' => 'Frequenza controllo (taglio)',
|
||||
'control_frequency_drawing' => 'Frequenza controllo disegno',
|
||||
'control_frequency_jig' => 'Frequenza controllo in dima',
|
||||
'control_mode_jig' => 'Modalità controllo in dima',
|
||||
'box_type' => 'Tipo scatola',
|
||||
'pallet_type' => 'Tipo bancale',
|
||||
'requested_package_code' => 'Confezione richiesta',
|
||||
];
|
||||
|
||||
// Selected category filter
|
||||
$categoryFilter = trim($_GET['cat'] ?? '');
|
||||
if ($categoryFilter !== '' && !array_key_exists($categoryFilter, $categories)) {
|
||||
$categoryFilter = '';
|
||||
}
|
||||
|
||||
// Load options
|
||||
$params = [];
|
||||
$sql = "
|
||||
SELECT id, category, value, label, sort_order, is_default, is_active, created_at, updated_at
|
||||
FROM ws_lookup_options
|
||||
";
|
||||
if ($categoryFilter !== '') {
|
||||
$sql .= " WHERE category = ? ";
|
||||
$params[] = $categoryFilter;
|
||||
}
|
||||
$sql .= " ORDER BY category ASC, sort_order ASC, label ASC, id ASC ";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$options = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
function h($v)
|
||||
{
|
||||
return htmlspecialchars((string)$v, ENT_QUOTES);
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php include('cssinclude.php'); ?>
|
||||
<title>Lookup Worksheet</title>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
|
||||
<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>
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/@ttskch/select2-bootstrap4-theme@1.5.2/dist/select2-bootstrap4.min.css" rel="stylesheet" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-size: 0.95rem;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.back-dashboard {
|
||||
background: #cfe3ff !important;
|
||||
color: #1f2d3d !important;
|
||||
border: 1px solid #bcd4f4 !important;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
padding: 10px 18px;
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background: #0d6efd;
|
||||
color: white;
|
||||
border-radius: 8px;
|
||||
padding: 10px 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.table thead {
|
||||
background: #cfe3ff;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.small-hint {
|
||||
color: #6b7280;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* Select2 sizing alignment */
|
||||
.select2-container .select2-selection--single {
|
||||
height: calc(2.375rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 1.6;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: calc(2.375rem + 2px);
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.badge-soft {
|
||||
background: #eef6ff;
|
||||
color: #1f2d3d;
|
||||
border: 1px solid #bcd4f4;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: #6b7280;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper toggled">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
<div class="card p-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="mb-0">Lookup Worksheet</h5>
|
||||
<div class="small-hint">Gestione valori predefiniti (tendine) per i campi dei fogli di lavoro</div>
|
||||
</div>
|
||||
<button class="btn back-dashboard" onclick="location.href='production_dashboard.php'">↩️ Dashboard</button>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div class="d-flex align-items-center gap-2" style="min-width: 420px;">
|
||||
<div class="fw-semibold">Categoria</div>
|
||||
<select id="categoryFilter" class="form-select">
|
||||
<option value="">-- Tutte --</option>
|
||||
<?php foreach ($categories as $key => $label): ?>
|
||||
<option value="<?= h($key) ?>" <?= $categoryFilter === $key ? 'selected' : '' ?>>
|
||||
<?= h($label) ?> (<?= h($key) ?>)
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-add" data-bs-toggle="modal" data-bs-target="#addModal">
|
||||
➕ Aggiungi valore
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="tabellaLookup" class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Category</th>
|
||||
<th>Value</th>
|
||||
<th>Label</th>
|
||||
<th>Ordine</th>
|
||||
<th>Default</th>
|
||||
<th>Attivo</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($options as $o): ?>
|
||||
<tr>
|
||||
<td><?= (int)$o['id'] ?></td>
|
||||
<td>
|
||||
<span class="badge badge-soft"><?= h($o['category']) ?></span>
|
||||
<div class="small-hint">
|
||||
<?= h($categories[$o['category']] ?? '-') ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="fw-semibold"><?= h($o['value']) ?></td>
|
||||
<td><?= h($o['label']) ?></td>
|
||||
<td><?= (int)$o['sort_order'] ?></td>
|
||||
<td><?= (int)$o['is_default'] === 1 ? '✅' : '-' ?></td>
|
||||
<td><?= (int)$o['is_active'] === 1 ? '✅' : '⛔' ?></td>
|
||||
<td class="text-nowrap">
|
||||
<button class="btn btn-sm btn-outline-primary edit-row"
|
||||
data-id="<?= (int)$o['id'] ?>"
|
||||
data-category="<?= h($o['category']) ?>"
|
||||
data-value="<?= h($o['value']) ?>"
|
||||
data-label="<?= h($o['label']) ?>"
|
||||
data-sort_order="<?= (int)$o['sort_order'] ?>"
|
||||
data-is_default="<?= (int)$o['is_default'] ?>"
|
||||
data-is_active="<?= (int)$o['is_active'] ?>">
|
||||
✏️ Modifica
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-row"
|
||||
data-id="<?= (int)$o['id'] ?>"
|
||||
data-name="<?= h($o['category'] . ' / ' . $o['value']) ?>">
|
||||
🗑️ Elimina
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="small-hint mt-2">
|
||||
Suggerimento: imposta <b>Default</b> solo per 1 valore per categoria (questa pagina lo gestisce automaticamente).
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<!-- MODAL ADD -->
|
||||
<div class="modal fade" id="addModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header" style="background:#cfe3ff;">
|
||||
<h5 class="modal-title">Aggiungi valore</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="addForm">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Categoria *</label>
|
||||
<select class="form-select" name="category" id="add_category" required>
|
||||
<option value="">-- Seleziona --</option>
|
||||
<?php foreach ($categories as $key => $label): ?>
|
||||
<option value="<?= h($key) ?>"><?= h($label) ?> (<?= h($key) ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="small-hint">Categoria = campo di destinazione nel worksheet</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Value *</label>
|
||||
<input type="text" class="form-control" name="value" placeholder="es. S, N, EUR, EACH_COIL" required>
|
||||
<div class="small-hint">Valore tecnico stabile (quello che salvi nel DB)</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label class="form-label fw-semibold">Label *</label>
|
||||
<input type="text" class="form-control" name="label" placeholder="Testo visibile in tendina" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Ordine</label>
|
||||
<input type="number" class="form-control" name="sort_order" value="100" min="1">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Default</label>
|
||||
<select class="form-select" name="is_default">
|
||||
<option value="0" selected>No</option>
|
||||
<option value="1">Sì</option>
|
||||
</select>
|
||||
<div class="small-hint">Se “Sì”, gli altri default della stessa categoria verranno disattivati</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Attivo</label>
|
||||
<select class="form-select" name="is_active">
|
||||
<option value="1" selected>Sì</option>
|
||||
<option value="0">No</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12 text-center mt-2">
|
||||
<button type="submit" class="btn btn-add">💾 Salva</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL EDIT -->
|
||||
<div class="modal fade" id="editModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header" style="background:#cfe3ff;">
|
||||
<h5 class="modal-title">Modifica valore</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editForm">
|
||||
<input type="hidden" name="id" id="edit_id">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Categoria *</label>
|
||||
<select class="form-select" name="category" id="edit_category" required>
|
||||
<option value="">-- Seleziona --</option>
|
||||
<?php foreach ($categories as $key => $label): ?>
|
||||
<option value="<?= h($key) ?>"><?= h($label) ?> (<?= h($key) ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Value *</label>
|
||||
<input type="text" class="form-control" name="value" id="edit_value" required>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label class="form-label fw-semibold">Label *</label>
|
||||
<input type="text" class="form-control" name="label" id="edit_label" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Ordine</label>
|
||||
<input type="number" class="form-control" name="sort_order" id="edit_sort_order" min="1">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Default</label>
|
||||
<select class="form-select" name="is_default" id="edit_is_default">
|
||||
<option value="0">No</option>
|
||||
<option value="1">Sì</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Attivo</label>
|
||||
<select class="form-select" name="is_active" id="edit_is_active">
|
||||
<option value="1">Sì</option>
|
||||
<option value="0">No</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12 text-center mt-2">
|
||||
<button type="submit" class="btn btn-add">💾 Salva modifiche</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
// DataTable
|
||||
$('#tabellaLookup').DataTable({
|
||||
pageLength: 50,
|
||||
lengthMenu: [10, 25, 50, 100],
|
||||
order: [
|
||||
[1, 'asc'],
|
||||
[4, 'asc'],
|
||||
[3, 'asc']
|
||||
],
|
||||
language: {
|
||||
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json'
|
||||
}
|
||||
});
|
||||
|
||||
// Select2 for category filter + modal selects
|
||||
$('#categoryFilter, #add_category, #edit_category').select2({
|
||||
theme: 'bootstrap4',
|
||||
width: '100%',
|
||||
placeholder: '-- Seleziona --',
|
||||
allowClear: true
|
||||
});
|
||||
|
||||
// Filter redirect
|
||||
$('#categoryFilter').on('change', function() {
|
||||
const v = $(this).val() || '';
|
||||
const base = window.location.pathname.split('/').pop();
|
||||
if (v === '') {
|
||||
window.location.href = base;
|
||||
} else {
|
||||
window.location.href = base + '?cat=' + encodeURIComponent(v);
|
||||
}
|
||||
});
|
||||
|
||||
// Add
|
||||
$('#addForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
formData.append('ajax', '1');
|
||||
formData.append('action', 'add');
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Salvato!',
|
||||
timer: 900
|
||||
})
|
||||
.then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Open edit modal
|
||||
$(document).on('click', '.edit-row', function() {
|
||||
const btn = $(this);
|
||||
|
||||
$('#edit_id').val(btn.data('id'));
|
||||
$('#edit_category').val(btn.data('category')).trigger('change');
|
||||
$('#edit_value').val(btn.data('value'));
|
||||
$('#edit_label').val(btn.data('label'));
|
||||
$('#edit_sort_order').val(btn.data('sort_order'));
|
||||
$('#edit_is_default').val(String(btn.data('is_default')));
|
||||
$('#edit_is_active').val(String(btn.data('is_active')));
|
||||
|
||||
const modal = new bootstrap.Modal(document.getElementById('editModal'));
|
||||
modal.show();
|
||||
});
|
||||
|
||||
// Save edit
|
||||
$('#editForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
formData.append('ajax', '1');
|
||||
formData.append('action', 'edit');
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Aggiornato!',
|
||||
timer: 900
|
||||
})
|
||||
.then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Delete
|
||||
$(document).on('click', '.delete-row', function() {
|
||||
const id = $(this).data('id');
|
||||
const name = $(this).data('name');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Confermi eliminazione?',
|
||||
text: name,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Sì, elimina',
|
||||
cancelButtonText: 'Annulla'
|
||||
}).then(result => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `ajax=1&action=delete&id=${id}`
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Eliminato!',
|
||||
timer: 900
|
||||
})
|
||||
.then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1008
public/userarea/manage-worksheet.php
Normal file
1008
public/userarea/manage-worksheet.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -341,12 +341,30 @@
|
||||
|
||||
<!-- 🔹 QUARTA RIGA: EMPLOYEES -->
|
||||
<div class="dashboard-grid-bottom" style="margin-top: 20px;">
|
||||
<button class="dash-btn dash-btn-small btn-skills" onclick="location.href='worksheets.php'">
|
||||
<div class="dash-icon">🛠️</div>
|
||||
<div>Fogli di lavoro</div>
|
||||
</button>
|
||||
<button class="dash-btn dash-btn-small btn-employees" onclick="location.href='employees.php'">
|
||||
<div class="dash-icon">👥</div>
|
||||
<div>Employees</div>
|
||||
</button>
|
||||
<button class="dash-btn dash-btn-small btn-skills" onclick="location.href='skills.php'">
|
||||
<div class="dash-icon">🛠️</div>
|
||||
<div>Skills</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 Quinta RIGA: EMPLOYEES -->
|
||||
<div class="dashboard-grid-bottom" style="margin-top: 20px;">
|
||||
<button class="dash-btn dash-btn-small btn-skills" onclick="location.href='lookup_values.php'">
|
||||
<div class="dash-icon">🛠️</div>
|
||||
<div>Setup</div>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ include('include/headscript.php');
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
|
||||
// AJAX salvataggio singolo (ora gestisce anche testo libero)
|
||||
// AJAX salvataggio singolo
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
@ -20,8 +20,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
||||
$pdo->prepare("DELETE FROM employee_skills WHERE employee_id = ? AND skill_id = ?")
|
||||
->execute([$employee_id, $skill_id]);
|
||||
|
||||
// Salva solo se c'è valore (non vuoto)
|
||||
if ($level !== '') {
|
||||
if ($level !== '' && $level !== '–') {
|
||||
$pdo->prepare("INSERT INTO employee_skills (employee_id, skill_id, level) VALUES (?, ?, ?)")
|
||||
->execute([$employee_id, $skill_id, $level]);
|
||||
}
|
||||
@ -47,7 +46,7 @@ $employees = $pdo->query("
|
||||
$skills = $pdo->query("
|
||||
SELECT
|
||||
s.id,
|
||||
s.name AS nome_completo,
|
||||
s.name,
|
||||
COALESCE(s.abbreviato, SUBSTRING(s.name, 1, 12)) AS acronimo,
|
||||
pl.line_number,
|
||||
pl.name AS linea
|
||||
@ -154,10 +153,9 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
|
||||
.table input[type="text"] {
|
||||
background: #fffacd;
|
||||
/* giallo chiaro per distinguere il campo testo */
|
||||
}
|
||||
|
||||
/* COLORI LIVELLI (solo per select) */
|
||||
/* COLORI LIVELLI */
|
||||
.level-Q {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
@ -195,6 +193,14 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Cella vuota / trattino */
|
||||
td:empty,
|
||||
td select option[value="–"]:checked~select,
|
||||
td input[value=""] {
|
||||
background: #f8f9fa !important;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
overflow-x: auto;
|
||||
}
|
||||
@ -229,7 +235,7 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
<tr>
|
||||
<?php foreach ($skills as $s): ?>
|
||||
<th class="skill-col skill-header"
|
||||
title="<?= htmlspecialchars($s['nome_completo']) ?>">
|
||||
title="<?= htmlspecialchars($s['name']) ?>">
|
||||
<?= htmlspecialchars($s['acronimo']) ?>
|
||||
</th>
|
||||
<?php endforeach; ?>
|
||||
@ -240,29 +246,33 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
<tr>
|
||||
<td class="fixed-name"><?= htmlspecialchars($emp['nome']) ?></td>
|
||||
<?php foreach ($skills as $s):
|
||||
$val = $livelli[$emp['id']][$s['id']] ?? '';
|
||||
$cls = str_replace(['.', ' '], '-', $val);
|
||||
// Default: trattino se non c'è valore
|
||||
$val = $livelli[$emp['id']][$s['id']] ?? '–';
|
||||
// Classe solo se valore reale (non trattino)
|
||||
$cls = ($val !== '–' && $val !== '') ? str_replace(['.', ' '], '-', $val) : '';
|
||||
?>
|
||||
<td>
|
||||
<?php if ($s['id'] == 29): ?>
|
||||
<!-- Campo testo libero per id=29 -->
|
||||
<!-- Campo testo: mostra vuoto se trattino -->
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
value="<?= htmlspecialchars($val) ?>"
|
||||
value="<?= $val === '–' ? '' : htmlspecialchars($val) ?>"
|
||||
onblur="salvaTesto(<?= $emp['id'] ?>, <?= $s['id'] ?>, this.value)">
|
||||
<?php else: ?>
|
||||
<!-- Tendina normale per tutte le altre -->
|
||||
<select class="form-select level-<?= $cls ?>"
|
||||
<!-- Tendina: include opzione "–" -->
|
||||
<select class="form-select <?= $cls ? 'level-' . $cls : '' ?>"
|
||||
onchange="salva(<?= $emp['id'] ?>, <?= $s['id'] ?>, this.value, this)">
|
||||
<?php if (strpos($s['nome_completo'], 'TURNO NOTTURNO') !== false): ?>
|
||||
<?php if (strpos($s['name'], 'TURNO NOTTURNO') !== false): ?>
|
||||
<option value="si" <?= $val === 'si' ? 'selected' : '' ?>>si</option>
|
||||
<option value="no" <?= $val === 'no' ? 'selected' : '' ?>>no</option>
|
||||
<option value="–" <?= $val === '–' ? 'selected' : '' ?>>–</option>
|
||||
<?php else: ?>
|
||||
<option value="DF" <?= $val === 'DF' ? 'selected' : '' ?>>DF</option>
|
||||
<option value="C" <?= $val === 'C' ? 'selected' : '' ?>>C</option>
|
||||
<option value="CQ" <?= $val === 'CQ' ? 'selected' : '' ?>>CQ</option>
|
||||
<option value="Q" <?= $val === 'Q' ? 'selected' : '' ?>>Q</option>
|
||||
<option value="NON RICH." <?= $val === 'NON RICH.' ? 'selected' : '' ?>>–</option>
|
||||
<option value="NON RICH." <?= $val === 'NON RICH.' ? 'selected' : '' ?>>NON RICH.</option>
|
||||
<option value="–" <?= $val === '–' ? 'selected' : '' ?>>–</option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
@ -282,7 +292,7 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Salvataggio per tendina (onchange)
|
||||
// Salvataggio per tendina
|
||||
function salva(empId, skillId, val, selectElement) {
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
@ -301,21 +311,14 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
showConfirmButton: false
|
||||
});
|
||||
|
||||
// Aggiorna colore SOLO se selectElement è valido
|
||||
if (selectElement && selectElement.tagName === 'SELECT') {
|
||||
// Rimuovi tutte le classi level-*
|
||||
selectElement.classList.forEach(c => {
|
||||
if (c.startsWith('level-')) selectElement.classList.remove(c);
|
||||
});
|
||||
|
||||
// Aggiungi la nuova classe level-*
|
||||
const newCls = 'level-' + val.replace(/[\.\s]/g, '-');
|
||||
selectElement.classList.add(newCls);
|
||||
|
||||
// (sicurezza) assicurati che resti form-select
|
||||
selectElement.className = selectElement.className.replace(/\blevel-[^\s]+\b/g, '').trim();
|
||||
if (val && val !== '–') {
|
||||
const newCls = 'level-' + val.replace(/[\.\s]/g, '-');
|
||||
selectElement.classList.add(newCls);
|
||||
}
|
||||
selectElement.classList.add('form-select');
|
||||
}
|
||||
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
@ -328,13 +331,13 @@ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
console.error('Fetch error:', err);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore rete o parsing',
|
||||
title: 'Errore rete',
|
||||
text: err.message || 'Controlla console'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Salvataggio per campo testo (onblur)
|
||||
// Salvataggio per testo
|
||||
function salvaTesto(empId, skillId, val) {
|
||||
val = val.trim();
|
||||
fetch('', {
|
||||
|
||||
530
public/userarea/skills.php
Normal file
530
public/userarea/skills.php
Normal file
@ -0,0 +1,530 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include('include/headscript.php');
|
||||
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
|
||||
// AJAX HANDLERS
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
try {
|
||||
if ($action === 'add') {
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$abbreviato = trim($_POST['abbreviato'] ?? '');
|
||||
$ordinamento = (int)($_POST['ordinamento'] ?? 999);
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
$production_line_id = $_POST['production_line_id'] !== '' ? (int)$_POST['production_line_id'] : null;
|
||||
$tool_id = $_POST['tool_id'] !== '' ? (int)$_POST['tool_id'] : null;
|
||||
$tool_note = trim($_POST['tool_note'] ?? '');
|
||||
|
||||
if ($name === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Nome obbligatorio']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO skills
|
||||
(name, abbreviato, ordinamento, description, production_line_id, tool_id, tool_note)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
$stmt->execute([$name, $abbreviato, $ordinamento, $description, $production_line_id, $tool_id, $tool_note]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action === 'edit') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$abbreviato = trim($_POST['abbreviato'] ?? '');
|
||||
$ordinamento = (int)($_POST['ordinamento'] ?? 999);
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
$production_line_id = $_POST['production_line_id'] !== '' ? (int)$_POST['production_line_id'] : null;
|
||||
$tool_id = $_POST['tool_id'] !== '' ? (int)$_POST['tool_id'] : null;
|
||||
$tool_note = trim($_POST['tool_note'] ?? '');
|
||||
|
||||
if ($id <= 0 || $name === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Dati non validi']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE skills SET
|
||||
name = ?, abbreviato = ?, ordinamento = ?, description = ?,
|
||||
production_line_id = ?, tool_id = ?, tool_note = ?
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt->execute([$name, $abbreviato, $ordinamento, $description, $production_line_id, $tool_id, $tool_note, $id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action === 'delete') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'ID non valido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM skills WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Elenco skills con nome tool
|
||||
$skills = $pdo->query("
|
||||
SELECT
|
||||
s.id,
|
||||
s.name,
|
||||
s.abbreviato,
|
||||
s.ordinamento,
|
||||
s.description,
|
||||
s.tool_id,
|
||||
s.tool_note,
|
||||
s.production_line_id,
|
||||
pl.name AS linea_name,
|
||||
pt.name AS tool_name,
|
||||
pt.registration_number
|
||||
FROM skills s
|
||||
LEFT JOIN production_lines pl ON s.production_line_id = pl.id
|
||||
LEFT JOIN production_tools pt ON s.tool_id = pt.id
|
||||
ORDER BY s.ordinamento ASC, s.id
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Linee produzione
|
||||
$lines = $pdo->query("SELECT id, name FROM production_lines ORDER BY line_number")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Attrezzature per tendina
|
||||
$tools = $pdo->query("
|
||||
SELECT id, name, registration_number
|
||||
FROM production_tools
|
||||
WHERE is_active = 1
|
||||
ORDER BY name
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php include('cssinclude.php'); ?>
|
||||
<title>Gestione Skills</title>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
|
||||
<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>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-size: 0.95rem;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.back-dashboard {
|
||||
background: #cfe3ff !important;
|
||||
color: #1f2d3d !important;
|
||||
border: 1px solid #bcd4f4 !important;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
padding: 10px 18px;
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background: #0d6efd;
|
||||
color: white;
|
||||
border-radius: 8px;
|
||||
padding: 10px 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.table thead {
|
||||
background: #cfe3ff;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 16px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper toggled">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
<div class="card p-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Gestione Skills</h5>
|
||||
<button class="btn back-dashboard" onclick="location.href='production_dashboard.php'">
|
||||
↩️ Dashboard
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="fw-semibold mb-0">Elenco Skills</h6>
|
||||
<button class="btn btn-add" data-bs-toggle="modal" data-bs-target="#addSkillModal">
|
||||
➕ Aggiungi Skill
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="tabellaSkills" class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Abbreviato</th>
|
||||
<th>Ordinamento</th>
|
||||
<th>Linea</th>
|
||||
<th>Attrezzatura</th>
|
||||
<th>Nota Tool</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($skills as $s): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($s['name']) ?></td>
|
||||
<td><?= htmlspecialchars($s['abbreviato'] ?? '-') ?></td>
|
||||
<td><?= (int)$s['ordinamento'] ?></td>
|
||||
<td><?= htmlspecialchars($s['linea_name'] ?? '-') ?></td>
|
||||
<td>
|
||||
<?php if ($s['tool_name']): ?>
|
||||
<?= htmlspecialchars($s['tool_name']) ?>
|
||||
<?php if ($s['registration_number']): ?>
|
||||
<small>(<?= htmlspecialchars($s['registration_number']) ?>)</small>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($s['tool_note'] ?? '-') ?></td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-primary edit-skill"
|
||||
data-id="<?= $s['id'] ?>"
|
||||
data-name="<?= htmlspecialchars($s['name'], ENT_QUOTES) ?>"
|
||||
data-abbreviato="<?= htmlspecialchars($s['abbreviato'] ?? '', ENT_QUOTES) ?>"
|
||||
data-ordinamento="<?= (int)$s['ordinamento'] ?>"
|
||||
data-description="<?= htmlspecialchars($s['description'] ?? '', ENT_QUOTES) ?>"
|
||||
data-line="<?= $s['production_line_id'] ?? '' ?>"
|
||||
data-tool_id="<?= $s['tool_id'] ?? '' ?>"
|
||||
data-tool_note="<?= htmlspecialchars($s['tool_note'] ?? '', ENT_QUOTES) ?>">
|
||||
✏️ Modifica
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-skill"
|
||||
data-id="<?= $s['id'] ?>"
|
||||
data-name="<?= htmlspecialchars($s['name'], ENT_QUOTES) ?>">
|
||||
🗑️ Elimina
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<!-- MODAL AGGIUNGI SKILL -->
|
||||
<div class="modal fade" id="addSkillModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header" style="background:#cfe3ff;">
|
||||
<h5 class="modal-title">Aggiungi Nuova Skill</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="addSkillForm">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Nome *</label>
|
||||
<input type="text" class="form-control" name="name" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Abbreviato</label>
|
||||
<input type="text" class="form-control" name="abbreviato">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label fw-semibold">Ordinamento</label>
|
||||
<input type="number" class="form-control" name="ordinamento" value="999" min="1">
|
||||
</div>
|
||||
<div class="col-md-8 mb-3">
|
||||
<label class="form-label fw-semibold">Linea di produzione</label>
|
||||
<select class="form-select" name="production_line_id">
|
||||
<option value="">-- Nessuna --</option>
|
||||
<?php foreach ($lines as $line): ?>
|
||||
<option value="<?= $line['id'] ?>"><?= htmlspecialchars($line['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Descrizione</label>
|
||||
<textarea class="form-control" name="description" rows="3"></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Attrezzatura / Tool</label>
|
||||
<select class="form-select" name="tool_id">
|
||||
<option value="">-- Nessuna --</option>
|
||||
<?php foreach ($tools as $tool): ?>
|
||||
<option value="<?= $tool['id'] ?>">
|
||||
<?= htmlspecialchars($tool['name']) ?>
|
||||
<?= $tool['registration_number'] ? ' (' . htmlspecialchars($tool['registration_number']) . ')' : '' ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Nota Tool</label>
|
||||
<input type="text" class="form-control" name="tool_note">
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-add">💾 Salva</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL MODIFICA SKILL -->
|
||||
<div class="modal fade" id="editSkillModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header" style="background:#cfe3ff;">
|
||||
<h5 class="modal-title">Modifica Skill</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editSkillForm">
|
||||
<input type="hidden" name="id" id="editId">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Nome *</label>
|
||||
<input type="text" class="form-control" name="name" id="editName" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Abbreviato</label>
|
||||
<input type="text" class="form-control" name="abbreviato" id="editAbbreviato">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label fw-semibold">Ordinamento</label>
|
||||
<input type="number" class="form-control" name="ordinamento" id="editOrdinamento" min="1">
|
||||
</div>
|
||||
<div class="col-md-8 mb-3">
|
||||
<label class="form-label fw-semibold">Linea di produzione</label>
|
||||
<select class="form-select" name="production_line_id" id="editLine">
|
||||
<option value="">-- Nessuna --</option>
|
||||
<?php foreach ($lines as $line): ?>
|
||||
<option value="<?= $line['id'] ?>"><?= htmlspecialchars($line['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Descrizione</label>
|
||||
<textarea class="form-control" name="description" id="editDescription" rows="3"></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Attrezzatura / Tool</label>
|
||||
<select class="form-select" name="tool_id" id="editToolId">
|
||||
<option value="">-- Nessuna --</option>
|
||||
<?php foreach ($tools as $tool): ?>
|
||||
<option value="<?= $tool['id'] ?>">
|
||||
<?= htmlspecialchars($tool['name']) ?>
|
||||
<?= $tool['registration_number'] ? ' (' . htmlspecialchars($tool['registration_number']) . ')' : '' ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-semibold">Nota Tool</label>
|
||||
<input type="text" class="form-control" name="tool_note" id="editToolNote">
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-add">💾 Salva Modifiche</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#tabellaSkills').DataTable({
|
||||
pageLength: 50,
|
||||
lengthMenu: [10, 25, 50, 100],
|
||||
order: [
|
||||
[3, 'asc']
|
||||
],
|
||||
language: {
|
||||
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json'
|
||||
}
|
||||
});
|
||||
|
||||
// Aggiungi
|
||||
$('#addSkillForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
formData.append('ajax', '1');
|
||||
formData.append('action', 'add');
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Aggiunta!',
|
||||
timer: 1000
|
||||
}).then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Modifica - apri modal
|
||||
$(document).on('click', '.edit-skill', function() {
|
||||
const btn = $(this);
|
||||
$('#editId').val(btn.data('id'));
|
||||
$('#editName').val(btn.data('name'));
|
||||
$('#editAbbreviato').val(btn.data('abbreviato'));
|
||||
$('#editOrdinamento').val(btn.data('ordinamento'));
|
||||
$('#editDescription').val(btn.data('description'));
|
||||
$('#editLine').val(btn.data('line'));
|
||||
$('#editToolId').val(btn.data('tool_id'));
|
||||
$('#editToolNote').val(btn.data('tool_note'));
|
||||
$('#editSkillModal').modal('show');
|
||||
});
|
||||
|
||||
// Salva modifica
|
||||
$('#editSkillForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
formData.append('ajax', '1');
|
||||
formData.append('action', 'edit');
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Modificata!',
|
||||
timer: 1000
|
||||
}).then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Elimina
|
||||
$(document).on('click', '.delete-skill', function() {
|
||||
const id = $(this).data('id');
|
||||
const name = $(this).data('name');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Confermi eliminazione?',
|
||||
text: `Skill: ${name}`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Sì, elimina',
|
||||
cancelButtonText: 'Annulla'
|
||||
}).then(result => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `ajax=1&action=delete&id=${id}`
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Eliminata!',
|
||||
timer: 1000
|
||||
}).then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
273
public/userarea/worksheets.php
Normal file
273
public/userarea/worksheets.php
Normal file
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include('include/headscript.php');
|
||||
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
|
||||
// AJAX HANDLERS
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
try {
|
||||
if ($action === 'delete') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'ID non valido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Delete header (rows will be deleted by FK cascade if constraints exist)
|
||||
$stmt = $pdo->prepare("DELETE FROM work_sheets WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Worksheets list + row count
|
||||
$worksheets = $pdo->query("
|
||||
SELECT
|
||||
ws.id,
|
||||
ws.worksheet_date,
|
||||
ws.customer_name,
|
||||
ws.profile_type_code,
|
||||
ws.approved_by,
|
||||
ws.created_at,
|
||||
m.nome AS matrice_nome,
|
||||
m.cliente AS matrice_cliente,
|
||||
(SELECT COUNT(*) FROM work_sheet_mescole wsm WHERE wsm.worksheet_id = ws.id) AS mixes_count
|
||||
FROM work_sheets ws
|
||||
LEFT JOIN matrice m ON ws.idmatrice = m.id
|
||||
ORDER BY ws.id DESC
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php include('cssinclude.php'); ?>
|
||||
<title>Fogli di Lavoro</title>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
|
||||
<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>
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/@ttskch/select2-bootstrap4-theme@1.5.2/dist/select2-bootstrap4.min.css" rel="stylesheet" />
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-size: 0.95rem;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.back-dashboard {
|
||||
background: #cfe3ff !important;
|
||||
color: #1f2d3d !important;
|
||||
border: 1px solid #bcd4f4 !important;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
padding: 10px 18px;
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background: #0d6efd;
|
||||
color: white;
|
||||
border-radius: 8px;
|
||||
padding: 10px 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.table thead {
|
||||
background: #cfe3ff;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
/* Select2 Bootstrap sizing alignment */
|
||||
.select2-container .select2-selection--single {
|
||||
height: calc(2.375rem + 2px);
|
||||
/* matches .form-select default height */
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 1.6;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: calc(2.375rem + 2px);
|
||||
}
|
||||
|
||||
/* Make it full width */
|
||||
.select2-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper toggled">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
<div class="card p-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Fogli di Lavoro</h5>
|
||||
<button class="btn back-dashboard" onclick="location.href='production_dashboard.php'">↩️ Dashboard</button>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="fw-semibold mb-0">Storico</h6>
|
||||
<button class="btn btn-add" onclick="location.href='manage-worksheet.php'">➕ Nuovo Foglio</button>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="tabellaWorksheets" class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Data</th>
|
||||
<th>Matrice/Profilo</th>
|
||||
<th>Cliente</th>
|
||||
<th>Codice Profilo</th>
|
||||
<th>Mescole</th>
|
||||
<th>Visto</th>
|
||||
<th>Creato</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($worksheets as $ws): ?>
|
||||
<tr>
|
||||
<td><?= (int)$ws['id'] ?></td>
|
||||
<td><?= htmlspecialchars($ws['worksheet_date'] ?? '-') ?></td>
|
||||
<td><?= htmlspecialchars($ws['matrice_nome'] ?? '-') ?></td>
|
||||
<td><?= htmlspecialchars($ws['customer_name'] ?: ($ws['matrice_cliente'] ?? '-')) ?></td>
|
||||
<td><?= htmlspecialchars($ws['profile_type_code'] ?? '-') ?></td>
|
||||
<td><?= (int)$ws['mixes_count'] ?></td>
|
||||
<td><?= htmlspecialchars($ws['approved_by'] ?? '-') ?></td>
|
||||
<td><?= htmlspecialchars($ws['created_at'] ?? '-') ?></td>
|
||||
<td class="text-nowrap">
|
||||
<button class="btn btn-sm btn-outline-primary"
|
||||
onclick="location.href='manage-worksheet.php?id=<?= (int)$ws['id'] ?>'">
|
||||
✏️ Modifica
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-outline-danger delete-ws"
|
||||
data-id="<?= (int)$ws['id'] ?>"
|
||||
data-name="<?= htmlspecialchars(($ws['matrice_nome'] ?? 'Foglio') . ' #' . $ws['id'], ENT_QUOTES) ?>">
|
||||
🗑️ Elimina
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#tabellaWorksheets').DataTable({
|
||||
pageLength: 50,
|
||||
lengthMenu: [10, 25, 50, 100],
|
||||
order: [
|
||||
[0, 'desc']
|
||||
],
|
||||
language: {
|
||||
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json'
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.delete-ws', function() {
|
||||
const id = $(this).data('id');
|
||||
const name = $(this).data('name');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Confermi eliminazione?',
|
||||
text: `${name}`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Sì, elimina',
|
||||
cancelButtonText: 'Annulla'
|
||||
}).then(result => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `ajax=1&action=delete&id=${id}`
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Eliminato!',
|
||||
timer: 900
|
||||
})
|
||||
.then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user