1566 lines
65 KiB
PHP
1566 lines
65 KiB
PHP
<?php
|
||
ob_start(); // buffer any accidental output
|
||
ini_set('display_errors', 1);
|
||
error_reporting(E_ALL);
|
||
|
||
include('include/headscript.php');
|
||
|
||
$db = DBHandlerSelect::getInstance();
|
||
$pdo = $db->getConnection();
|
||
|
||
$worksheet_id = isset($_GET['id']) && is_numeric($_GET['id']) ? (int)$_GET['id'] : 0;
|
||
|
||
// AJAX HANDLERS
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||
// Ensure clean JSON output
|
||
while (ob_get_level()) {
|
||
ob_end_clean();
|
||
}
|
||
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
|
||
$action = $_POST['action'] ?? '';
|
||
|
||
try {
|
||
// Save header (insert/update)
|
||
if ($action === 'save_header') {
|
||
$idmatrice = (int)($_POST['idmatrice'] ?? 0);
|
||
if ($idmatrice <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'Seleziona una matrice/profilo']);
|
||
exit;
|
||
}
|
||
|
||
$id = (int)($_POST['id'] ?? 0);
|
||
|
||
$worksheet_date = $_POST['worksheet_date'] !== '' ? $_POST['worksheet_date'] : null;
|
||
$customer_name = trim($_POST['customer_name'] ?? '');
|
||
$profile_code = trim($_POST['profile_type_code'] ?? '');
|
||
$marking = ($_POST['marking'] ?? '') !== '' ? $_POST['marking'] : null;
|
||
|
||
$prod_control = trim($_POST['prod_control_measure_settings'] ?? '');
|
||
|
||
$freq_cut = trim($_POST['control_frequency_cut'] ?? '');
|
||
$freq_draw = trim($_POST['control_frequency_drawing'] ?? '');
|
||
$freq_jig = trim($_POST['control_frequency_jig'] ?? '');
|
||
$mode_jig = trim($_POST['control_mode_jig'] ?? '');
|
||
|
||
// Package data moved to worksheet header
|
||
$requested_package_code = trim($_POST['requested_package_code'] ?? '');
|
||
$meters_per_package = $_POST['meters_per_package'] !== '' ? (int)$_POST['meters_per_package'] : null;
|
||
$meters_per_package_tolerance = trim($_POST['meters_per_package_tolerance'] ?? '');
|
||
$meters_per_package_notes = trim($_POST['meters_per_package_notes'] ?? '');
|
||
|
||
$box_type = trim($_POST['box_type'] ?? '');
|
||
$pkg_box = $_POST['packages_or_pieces_per_box'] !== '' ? (int)$_POST['packages_or_pieces_per_box'] : null;
|
||
$m_box = $_POST['meters_per_box'] !== '' ? (int)$_POST['meters_per_box'] : null;
|
||
|
||
$pallet_type = trim($_POST['pallet_type'] ?? '');
|
||
$per_pallet = $_POST['boxes_or_packages_per_pallet'] !== '' ? (int)$_POST['boxes_or_packages_per_pallet'] : null;
|
||
|
||
$sp_exp_kg = $_POST['speed_expected_kg_h'] !== '' ? (float)$_POST['speed_expected_kg_h'] : null;
|
||
$sp_act_kg = $_POST['speed_actual_kg_h'] !== '' ? (float)$_POST['speed_actual_kg_h'] : null;
|
||
$sp_exp_m = $_POST['speed_expected_m_h'] !== '' ? (float)$_POST['speed_expected_m_h'] : null;
|
||
$sp_act_m = $_POST['speed_actual_m_h'] !== '' ? (float)$_POST['speed_actual_m_h'] : null;
|
||
|
||
$approved_by = trim($_POST['approved_by'] ?? '');
|
||
$notes = trim($_POST['notes'] ?? '');
|
||
$worksheet_number = null;
|
||
|
||
if ($id > 0) {
|
||
$stmt = $pdo->prepare("
|
||
UPDATE work_sheets SET
|
||
idmatrice = ?,
|
||
worksheet_date = ?,
|
||
customer_name = ?,
|
||
profile_type_code = ?,
|
||
marking = ?,
|
||
prod_control_measure_settings = ?,
|
||
control_frequency_cut = ?,
|
||
control_frequency_drawing = ?,
|
||
control_frequency_jig = ?,
|
||
control_mode_jig = ?,
|
||
requested_package_code = ?,
|
||
meters_per_package = ?,
|
||
meters_per_package_tolerance = ?,
|
||
meters_per_package_notes = ?,
|
||
box_type = ?,
|
||
packages_or_pieces_per_box = ?,
|
||
meters_per_box = ?,
|
||
pallet_type = ?,
|
||
boxes_or_packages_per_pallet = ?,
|
||
speed_expected_kg_h = ?,
|
||
speed_actual_kg_h = ?,
|
||
speed_expected_m_h = ?,
|
||
speed_actual_m_h = ?,
|
||
approved_by = ?,
|
||
notes = ?
|
||
WHERE id = ?
|
||
");
|
||
$stmt->execute([
|
||
$idmatrice,
|
||
$worksheet_date,
|
||
$customer_name !== '' ? $customer_name : null,
|
||
$profile_code !== '' ? $profile_code : null,
|
||
$marking,
|
||
$prod_control !== '' ? $prod_control : null,
|
||
$freq_cut !== '' ? $freq_cut : null,
|
||
$freq_draw !== '' ? $freq_draw : null,
|
||
$freq_jig !== '' ? $freq_jig : null,
|
||
$mode_jig !== '' ? $mode_jig : null,
|
||
$requested_package_code !== '' ? $requested_package_code : null,
|
||
$meters_per_package,
|
||
$meters_per_package_tolerance !== '' ? $meters_per_package_tolerance : null,
|
||
$meters_per_package_notes !== '' ? $meters_per_package_notes : null,
|
||
$box_type !== '' ? $box_type : null,
|
||
$pkg_box,
|
||
$m_box,
|
||
$pallet_type !== '' ? $pallet_type : null,
|
||
$per_pallet,
|
||
$sp_exp_kg,
|
||
$sp_act_kg,
|
||
$sp_exp_m,
|
||
$sp_act_m,
|
||
$approved_by !== '' ? $approved_by : null,
|
||
$notes !== '' ? $notes : null,
|
||
$id
|
||
]);
|
||
|
||
echo json_encode(['success' => true, 'id' => $id]);
|
||
exit;
|
||
}
|
||
|
||
$pdo->beginTransaction();
|
||
|
||
$stmtNum = $pdo->query("
|
||
SELECT IFNULL(MAX(worksheet_number), 0) + 1 AS next_number
|
||
FROM work_sheets
|
||
");
|
||
$worksheet_number = (int)$stmtNum->fetchColumn();
|
||
if ($worksheet_number <= 0) {
|
||
$worksheet_number = 1;
|
||
}
|
||
|
||
$stmt = $pdo->prepare("
|
||
INSERT INTO work_sheets
|
||
(
|
||
worksheet_number,
|
||
idmatrice,
|
||
worksheet_date,
|
||
customer_name,
|
||
profile_type_code,
|
||
revision_code,
|
||
worksheet_status,
|
||
marking,
|
||
prod_control_measure_settings,
|
||
control_frequency_cut,
|
||
control_frequency_drawing,
|
||
control_frequency_jig,
|
||
control_mode_jig,
|
||
requested_package_code,
|
||
meters_per_package,
|
||
meters_per_package_tolerance,
|
||
meters_per_package_notes,
|
||
box_type,
|
||
packages_or_pieces_per_box,
|
||
meters_per_box,
|
||
pallet_type,
|
||
boxes_or_packages_per_pallet,
|
||
speed_expected_kg_h,
|
||
speed_actual_kg_h,
|
||
speed_expected_m_h,
|
||
speed_actual_m_h,
|
||
approved_by,
|
||
notes
|
||
)
|
||
VALUES
|
||
(
|
||
?, ?, ?, ?, ?, ?, ?,
|
||
?, ?, ?, ?, ?, ?,
|
||
?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||
?, ?, ?, ?, ?, ?
|
||
)
|
||
");
|
||
$stmt->execute([
|
||
$worksheet_number,
|
||
$idmatrice,
|
||
$worksheet_date,
|
||
$customer_name !== '' ? $customer_name : null,
|
||
$profile_code !== '' ? $profile_code : null,
|
||
null, // revision_code = vuoto => revisione 0
|
||
'active', // worksheet_status
|
||
$marking,
|
||
$prod_control !== '' ? $prod_control : null,
|
||
$freq_cut !== '' ? $freq_cut : null,
|
||
$freq_draw !== '' ? $freq_draw : null,
|
||
$freq_jig !== '' ? $freq_jig : null,
|
||
$mode_jig !== '' ? $mode_jig : null,
|
||
$requested_package_code !== '' ? $requested_package_code : null,
|
||
$meters_per_package,
|
||
$meters_per_package_tolerance !== '' ? $meters_per_package_tolerance : null,
|
||
$meters_per_package_notes !== '' ? $meters_per_package_notes : null,
|
||
$box_type !== '' ? $box_type : null,
|
||
$pkg_box,
|
||
$m_box,
|
||
$pallet_type !== '' ? $pallet_type : null,
|
||
$per_pallet,
|
||
$sp_exp_kg,
|
||
$sp_act_kg,
|
||
$sp_exp_m,
|
||
$sp_act_m,
|
||
$approved_by !== '' ? $approved_by : null,
|
||
$notes !== '' ? $notes : null
|
||
]);
|
||
|
||
$newId = (int)$pdo->lastInsertId();
|
||
$pdo->commit();
|
||
|
||
echo json_encode([
|
||
'success' => true,
|
||
'id' => $newId,
|
||
'worksheet_number' => $worksheet_number,
|
||
'worksheet_number_label' => worksheet_number_label($worksheet_number)
|
||
]);
|
||
exit;
|
||
}
|
||
|
||
// Add or edit mix row
|
||
if ($action === 'save_mix_row') {
|
||
$worksheet_id = (int)($_POST['worksheet_id'] ?? 0);
|
||
if ($worksheet_id <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'Salva prima il foglio (testata)']);
|
||
exit;
|
||
}
|
||
|
||
$row_id = (int)($_POST['row_id'] ?? 0);
|
||
$idmescola = (int)($_POST['idmescola'] ?? 0);
|
||
$pos = 0; // auto-assign
|
||
|
||
if ($idmescola <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'Seleziona una mescola']);
|
||
exit;
|
||
}
|
||
if ($pos <= 0) $pos = 1;
|
||
|
||
$mix_weight = $_POST['mix_weight_g_m'] !== '' ? (float)$_POST['mix_weight_g_m'] : null;
|
||
$density = trim($_POST['required_density'] ?? '');
|
||
$hardness = trim($_POST['required_hardness_shore_a'] ?? '');
|
||
|
||
$lub_type = ($_POST['lubrication_type'] ?? '') !== '' ? $_POST['lubrication_type'] : null;
|
||
$lub_note = trim($_POST['lubrication_notes'] ?? '');
|
||
|
||
$pdo->beginTransaction();
|
||
|
||
if ($row_id > 0) {
|
||
$stmt = $pdo->prepare("
|
||
UPDATE work_sheet_mescole SET
|
||
idmescola = ?,
|
||
mix_weight_g_m = ?,
|
||
required_density = ?,
|
||
required_hardness_shore_a = ?,
|
||
lubrication_type = ?,
|
||
lubrication_notes = ?
|
||
WHERE id = ? AND worksheet_id = ?
|
||
");
|
||
$stmt->execute([
|
||
$idmescola,
|
||
$mix_weight,
|
||
$density !== '' ? $density : null,
|
||
$hardness !== '' ? $hardness : null,
|
||
$lub_type,
|
||
$lub_note !== '' ? $lub_note : null,
|
||
$row_id,
|
||
$worksheet_id
|
||
]);
|
||
|
||
$pdo->commit();
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
}
|
||
|
||
$stmtPos = $pdo->prepare("
|
||
SELECT IFNULL(MAX(mix_position), 0) + 1
|
||
FROM work_sheet_mescole
|
||
WHERE worksheet_id = ?
|
||
FOR UPDATE
|
||
");
|
||
$stmtPos->execute([$worksheet_id]);
|
||
$pos = (int)$stmtPos->fetchColumn();
|
||
if ($pos <= 0) $pos = 1;
|
||
|
||
$stmt = $pdo->prepare("
|
||
INSERT INTO work_sheet_mescole
|
||
(
|
||
worksheet_id, idmescola, mix_position, mix_weight_g_m,
|
||
required_density, required_hardness_shore_a,
|
||
lubrication_type, lubrication_notes
|
||
)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||
");
|
||
$stmt->execute([
|
||
$worksheet_id,
|
||
$idmescola,
|
||
$pos,
|
||
$mix_weight,
|
||
$density !== '' ? $density : null,
|
||
$hardness !== '' ? $hardness : null,
|
||
$lub_type,
|
||
$lub_note !== '' ? $lub_note : null
|
||
]);
|
||
|
||
$pdo->commit();
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
}
|
||
|
||
// Delete mix row
|
||
if ($action === 'delete_mix_row') {
|
||
$row_id = (int)($_POST['row_id'] ?? 0);
|
||
if ($row_id <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'ID riga non valido']);
|
||
exit;
|
||
}
|
||
|
||
$stmt = $pdo->prepare("DELETE FROM work_sheet_mescole WHERE id = ?");
|
||
$stmt->execute([$row_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;
|
||
}
|
||
}
|
||
|
||
// Load matrices dropdown
|
||
$matrici = $pdo->query("
|
||
SELECT id, nome, cliente
|
||
FROM matrice
|
||
ORDER BY nome ASC
|
||
")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
// Load generic worksheet lookup options
|
||
$lookup = [];
|
||
$lookupDefault = [];
|
||
|
||
$stmt = $pdo->prepare("
|
||
SELECT category, value, label, is_default
|
||
FROM ws_lookup_options
|
||
WHERE is_active = 1
|
||
ORDER BY category ASC, sort_order ASC, label ASC
|
||
");
|
||
$stmt->execute();
|
||
|
||
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||
$lookup[$r['category']][] = $r;
|
||
|
||
if ((int)$r['is_default'] === 1 && !isset($lookupDefault[$r['category']])) {
|
||
$lookupDefault[$r['category']] = $r['value'];
|
||
}
|
||
}
|
||
|
||
// Load packaging items from dedicated table
|
||
$packagingLookup = [
|
||
'PACKAGING_TYPE' => [],
|
||
'BOX' => [],
|
||
'PALLET' => []
|
||
];
|
||
|
||
$stmt = $pdo->prepare("
|
||
SELECT category, item_name, item_code
|
||
FROM packaging_items
|
||
WHERE is_active = 1
|
||
AND category IN ('PACKAGING_TYPE', 'BOX', 'PALLET')
|
||
ORDER BY category ASC, item_name ASC
|
||
");
|
||
$stmt->execute();
|
||
|
||
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||
$label = $r['item_name'];
|
||
if (!empty($r['item_code'])) {
|
||
$label .= ' — ' . $r['item_code'];
|
||
}
|
||
|
||
$packagingLookup[$r['category']][] = [
|
||
'value' => $r['item_code'],
|
||
'label' => $label
|
||
];
|
||
}
|
||
|
||
// Load mescole dropdown for modal
|
||
$mescole = $pdo->query("
|
||
SELECT id, nome, nomeuscita
|
||
FROM mescole
|
||
ORDER BY nome ASC
|
||
")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
// Load worksheet (edit)
|
||
$worksheet = null;
|
||
$mixRows = [];
|
||
|
||
if ($worksheet_id > 0) {
|
||
$stmt = $pdo->prepare("
|
||
SELECT ws.*, m.nome AS matrice_nome
|
||
FROM work_sheets ws
|
||
LEFT JOIN matrice m ON ws.idmatrice = m.id
|
||
WHERE ws.id = ?
|
||
");
|
||
$stmt->execute([$worksheet_id]);
|
||
$worksheet = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if ($worksheet) {
|
||
$stmt = $pdo->prepare("
|
||
SELECT
|
||
wsm.*,
|
||
me.nome AS mescola_nome,
|
||
me.nomeuscita AS mescola_uscita
|
||
FROM work_sheet_mescole wsm
|
||
LEFT JOIN mescole me ON me.id = wsm.idmescola
|
||
WHERE wsm.worksheet_id = ?
|
||
ORDER BY wsm.mix_position ASC, wsm.id ASC
|
||
");
|
||
$stmt->execute([$worksheet_id]);
|
||
$mixRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||
} else {
|
||
$worksheet_id = 0;
|
||
}
|
||
}
|
||
|
||
// Helpers
|
||
function h($v)
|
||
{
|
||
return htmlspecialchars((string)$v, ENT_QUOTES);
|
||
}
|
||
|
||
function worksheet_number_label($n)
|
||
{
|
||
$n = (int)$n;
|
||
return $n > 0 ? 'FL' . $n : 'Non assegnato';
|
||
}
|
||
|
||
function ws_options($rows, $selectedValue, $defaultValue = '')
|
||
{
|
||
$selectedValue = (string)$selectedValue;
|
||
if ($selectedValue === '' && $defaultValue !== '') {
|
||
$selectedValue = (string)$defaultValue;
|
||
}
|
||
|
||
$html = '<option value="">--</option>';
|
||
if (!$rows) return $html;
|
||
|
||
foreach ($rows as $r) {
|
||
$val = h($r['value']);
|
||
$lab = h($r['label']);
|
||
$sel = ((string)$r['value'] === $selectedValue) ? ' selected' : '';
|
||
$html .= "<option value=\"{$val}\"{$sel}>{$lab}</option>";
|
||
}
|
||
return $html;
|
||
}
|
||
|
||
function packaging_options($rows, $selectedValue = '')
|
||
{
|
||
$selectedValue = (string)$selectedValue;
|
||
|
||
$html = '<option value="">--</option>';
|
||
if (!$rows) return $html;
|
||
|
||
foreach ($rows as $r) {
|
||
$val = h($r['value']);
|
||
$lab = h($r['label']);
|
||
$sel = ((string)$r['value'] === $selectedValue) ? ' selected' : '';
|
||
$html .= "<option value=\"{$val}\"{$sel}>{$lab}</option>";
|
||
}
|
||
|
||
return $html;
|
||
}
|
||
|
||
$isEdit = ($worksheet_id > 0);
|
||
?>
|
||
<!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><?= $isEdit ? 'Modifica Foglio di Lavoro' : 'Nuovo Foglio di Lavoro' ?></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.96rem;
|
||
background:
|
||
radial-gradient(circle at top right, rgba(59, 130, 246, 0.08), transparent 24%),
|
||
radial-gradient(circle at bottom left, rgba(16, 185, 129, 0.07), transparent 28%),
|
||
#f4f7fb;
|
||
}
|
||
|
||
.page-title-wrap {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
gap: 15px;
|
||
flex-wrap: wrap;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.page-title-box {
|
||
background: linear-gradient(135deg, #1d4ed8, #2563eb);
|
||
color: #fff;
|
||
border-radius: 20px;
|
||
padding: 22px 24px;
|
||
box-shadow: 0 14px 35px rgba(37, 99, 235, 0.18);
|
||
flex: 1 1 auto;
|
||
}
|
||
|
||
.page-title-box h4 {
|
||
color: #fff;
|
||
margin-bottom: 6px;
|
||
font-weight: 800;
|
||
}
|
||
|
||
.page-title-box .subtitle {
|
||
margin: 0;
|
||
color: rgba(255, 255, 255, 0.92);
|
||
font-size: 0.93rem;
|
||
}
|
||
|
||
.top-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.btn-history {
|
||
background: #fff !important;
|
||
color: #1f2937 !important;
|
||
border: 1px solid #dbe3ef !important;
|
||
border-radius: 12px;
|
||
font-weight: 700;
|
||
padding: 11px 18px;
|
||
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.06);
|
||
}
|
||
|
||
.main-card {
|
||
border: 0;
|
||
border-radius: 22px;
|
||
overflow: hidden;
|
||
box-shadow: 0 12px 34px rgba(15, 23, 42, 0.08);
|
||
background: #fff;
|
||
}
|
||
|
||
.section-block {
|
||
border: 1px solid #e7edf5;
|
||
border-radius: 18px;
|
||
background: #fff;
|
||
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.03);
|
||
overflow: hidden;
|
||
margin-bottom: 18px;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
padding: 14px 18px;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
||
}
|
||
|
||
.section-header h6 {
|
||
margin: 0;
|
||
font-size: 1rem;
|
||
font-weight: 800;
|
||
}
|
||
|
||
.section-header .section-hint {
|
||
font-size: 0.84rem;
|
||
opacity: 0.92;
|
||
margin: 0;
|
||
}
|
||
|
||
.section-body {
|
||
padding: 18px;
|
||
}
|
||
|
||
.theme-blue .section-header {
|
||
background: linear-gradient(135deg, #dbeafe, #bfdbfe);
|
||
color: #123b7a;
|
||
}
|
||
|
||
.theme-green .section-header {
|
||
background: linear-gradient(135deg, #dcfce7, #bbf7d0);
|
||
color: #14532d;
|
||
}
|
||
|
||
.theme-orange .section-header {
|
||
background: linear-gradient(135deg, #ffedd5, #fed7aa);
|
||
color: #9a3412;
|
||
}
|
||
|
||
.theme-purple .section-header {
|
||
background: linear-gradient(135deg, #ede9fe, #ddd6fe);
|
||
color: #5b21b6;
|
||
}
|
||
|
||
.theme-gray .section-header {
|
||
background: linear-gradient(135deg, #f3f4f6, #e5e7eb);
|
||
color: #374151;
|
||
}
|
||
|
||
.theme-cyan .section-header {
|
||
background: linear-gradient(135deg, #cffafe, #a5f3fc);
|
||
color: #155e75;
|
||
}
|
||
|
||
.section-grid-note {
|
||
font-size: 0.84rem;
|
||
color: #6b7280;
|
||
margin-top: -4px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.form-label {
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.form-control,
|
||
.form-select {
|
||
border-radius: 12px;
|
||
min-height: 46px;
|
||
border: 1px solid #d7e0ea;
|
||
box-shadow: none !important;
|
||
}
|
||
|
||
textarea.form-control {
|
||
min-height: auto;
|
||
}
|
||
|
||
.form-control:focus,
|
||
.form-select:focus {
|
||
border-color: #60a5fa;
|
||
}
|
||
|
||
.input-tip {
|
||
font-size: 0.79rem;
|
||
color: #6b7280;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
.required-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
background: #fee2e2;
|
||
color: #991b1b;
|
||
border-radius: 999px;
|
||
padding: 5px 10px;
|
||
font-size: 0.77rem;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.soft-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
background: #eef2ff;
|
||
color: #3730a3;
|
||
border-radius: 999px;
|
||
padding: 5px 10px;
|
||
font-size: 0.77rem;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.action-bar {
|
||
position: sticky;
|
||
bottom: 12px;
|
||
z-index: 20;
|
||
background: rgba(255, 255, 255, 0.92);
|
||
backdrop-filter: blur(8px);
|
||
border: 1px solid #e5edf6;
|
||
border-radius: 18px;
|
||
padding: 14px;
|
||
box-shadow: 0 10px 28px rgba(15, 23, 42, 0.10);
|
||
margin-top: 14px;
|
||
}
|
||
|
||
.btn-main-save {
|
||
background: linear-gradient(135deg, #16a34a, #22c55e);
|
||
color: #fff;
|
||
border: 0;
|
||
border-radius: 12px;
|
||
padding: 12px 22px;
|
||
font-weight: 800;
|
||
box-shadow: 0 10px 24px rgba(34, 197, 94, 0.18);
|
||
}
|
||
|
||
.btn-main-save:hover {
|
||
color: #fff;
|
||
opacity: 0.96;
|
||
}
|
||
|
||
.btn-mix {
|
||
background: linear-gradient(135deg, #2563eb, #3b82f6);
|
||
color: #fff;
|
||
border: 0;
|
||
border-radius: 12px;
|
||
padding: 12px 20px;
|
||
font-weight: 800;
|
||
box-shadow: 0 10px 24px rgba(59, 130, 246, 0.18);
|
||
}
|
||
|
||
.btn-mix:disabled {
|
||
background: #cbd5e1;
|
||
box-shadow: none;
|
||
color: #fff;
|
||
}
|
||
|
||
.summary-strip {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||
gap: 12px;
|
||
margin-bottom: 18px;
|
||
}
|
||
|
||
.summary-item {
|
||
background: #fff;
|
||
border: 1px solid #e5edf6;
|
||
border-radius: 16px;
|
||
padding: 14px 16px;
|
||
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.04);
|
||
}
|
||
|
||
.summary-item .label {
|
||
font-size: 0.80rem;
|
||
color: #6b7280;
|
||
margin-bottom: 4px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.summary-item .value {
|
||
font-size: 1rem;
|
||
color: #111827;
|
||
font-weight: 800;
|
||
}
|
||
|
||
.table-wrap {
|
||
border: 1px solid #e5edf6;
|
||
border-radius: 18px;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
}
|
||
|
||
.table thead th {
|
||
background: #e0efff !important;
|
||
color: #163a63;
|
||
font-weight: 800;
|
||
border-bottom: 1px solid #cde0f6 !important;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.table td {
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.mix-table-title {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
flex-wrap: wrap;
|
||
margin-bottom: 14px;
|
||
}
|
||
|
||
.mix-table-title h5 {
|
||
margin: 0;
|
||
font-weight: 800;
|
||
color: #111827;
|
||
}
|
||
|
||
.mix-helper {
|
||
color: #6b7280;
|
||
font-size: 0.86rem;
|
||
}
|
||
|
||
.mini-pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
border-radius: 999px;
|
||
padding: 4px 9px;
|
||
font-size: 0.75rem;
|
||
font-weight: 700;
|
||
background: #eef6ff;
|
||
color: #1d4ed8;
|
||
}
|
||
|
||
.modal-content {
|
||
border-radius: 20px;
|
||
overflow: hidden;
|
||
border: 0;
|
||
box-shadow: 0 18px 44px rgba(15, 23, 42, 0.18);
|
||
}
|
||
|
||
.modal-header {
|
||
border-bottom: 0;
|
||
padding: 16px 20px;
|
||
}
|
||
|
||
.modal-body {
|
||
padding: 20px;
|
||
}
|
||
|
||
.mix-modal-head {
|
||
background: linear-gradient(135deg, #dbeafe, #bfdbfe);
|
||
color: #123b7a;
|
||
}
|
||
|
||
.select2-container--bootstrap4 .select2-selection {
|
||
min-height: 46px !important;
|
||
border-radius: 12px !important;
|
||
border-color: #d7e0ea !important;
|
||
}
|
||
|
||
.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered {
|
||
line-height: 44px !important;
|
||
}
|
||
|
||
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow {
|
||
height: 44px !important;
|
||
}
|
||
|
||
@media (max-width: 992px) {
|
||
.summary-strip {
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
}
|
||
}
|
||
|
||
@media (max-width: 576px) {
|
||
.summary-strip {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.page-title-box {
|
||
padding: 18px;
|
||
}
|
||
|
||
.section-body {
|
||
padding: 14px;
|
||
}
|
||
|
||
.action-bar {
|
||
padding: 12px;
|
||
}
|
||
}
|
||
</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="page-title-wrap">
|
||
<div class="page-title-box">
|
||
<h4><?= $isEdit ? 'Modifica Foglio di Lavoro' : 'Nuovo Foglio di Lavoro' ?></h4>
|
||
<p class="subtitle">
|
||
Pagina pensata per uso operativo in produzione: prima salva la testata, poi inserisci le mescole
|
||
</p>
|
||
</div>
|
||
|
||
<div class="top-actions">
|
||
<button class="btn btn-history" onclick="location.href='worksheets.php'">↩️ Storico fogli</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="summary-strip">
|
||
<div class="summary-item">
|
||
<div class="label">Stato foglio</div>
|
||
<div class="value"><?= $isEdit ? 'In modifica' : 'Nuovo foglio' ?></div>
|
||
</div>
|
||
<div class="summary-item">
|
||
<div class="label">Foglio / Revisione</div>
|
||
<div class="value" id="summaryWsId">
|
||
<?php
|
||
$wsNumberLabel = ($worksheet && !empty($worksheet['worksheet_number']))
|
||
? worksheet_number_label($worksheet['worksheet_number'])
|
||
: 'Non assegnato';
|
||
|
||
$wsRevisionLabel = ($worksheet && isset($worksheet['revision_code']) && trim((string)$worksheet['revision_code']) !== '')
|
||
? trim((string)$worksheet['revision_code'])
|
||
: '0';
|
||
|
||
echo h($wsNumberLabel . ' / Rev. ' . $wsRevisionLabel);
|
||
?>
|
||
</div>
|
||
</div>
|
||
<div class="summary-item">
|
||
<div class="label">Mescole inserite</div>
|
||
<div class="value"><?= count($mixRows) ?></div>
|
||
</div>
|
||
<div class="summary-item">
|
||
<div class="label">Passaggio operativo</div>
|
||
<div class="value"><?= $worksheet_id > 0 ? 'Puoi aggiungere mescole' : 'Salva prima la testata' ?></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card main-card">
|
||
<div class="card-body p-4 p-lg-4">
|
||
|
||
<form id="worksheetHeaderForm">
|
||
<input type="hidden" name="id" id="wsId" value="<?= (int)$worksheet_id ?>">
|
||
|
||
<div class="section-block theme-blue">
|
||
<div class="section-header">
|
||
<div>
|
||
<h6>1. Dati principali del foglio</h6>
|
||
<p class="section-hint mb-0">Campi iniziali per identificare il lavoro</p>
|
||
</div>
|
||
<div class="required-badge">Obbligatorio: matrice / profilo</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="row g-3">
|
||
<div class="col-lg-6">
|
||
<label class="form-label">Matrice / Profilo *</label>
|
||
<select class="form-select" name="idmatrice" id="idmatrice" required>
|
||
<option value="">-- Seleziona --</option>
|
||
<?php foreach ($matrici as $m): ?>
|
||
<option value="<?= (int)$m['id'] ?>"
|
||
<?= $worksheet && (int)$worksheet['idmatrice'] === (int)$m['id'] ? 'selected' : '' ?>>
|
||
<?= h($m['nome']) ?><?= $m['cliente'] ? ' — ' . h($m['cliente']) : '' ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<div class="input-tip">Seleziona il profilo da produrre</div>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Data foglio</label>
|
||
<input type="date" class="form-control" name="worksheet_date"
|
||
value="<?= $worksheet ? h($worksheet['worksheet_date']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Codice profilo</label>
|
||
<input type="text" class="form-control" name="profile_type_code"
|
||
value="<?= $worksheet ? h($worksheet['profile_type_code']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-6">
|
||
<label class="form-label">Cliente (override)</label>
|
||
<input type="text" class="form-control" name="customer_name"
|
||
value="<?= $worksheet ? h($worksheet['customer_name']) : '' ?>">
|
||
<div class="input-tip">Compila solo se vuoi specificare un nome cliente manuale</div>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Marchiatura</label>
|
||
<select class="form-select" name="marking" id="marking">
|
||
<?= ws_options($lookup['marking'] ?? [], $worksheet['marking'] ?? '', $lookupDefault['marking'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Visto / Approvazione</label>
|
||
<input type="text" class="form-control" name="approved_by"
|
||
value="<?= $worksheet ? h($worksheet['approved_by']) : '' ?>">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-block theme-green">
|
||
<div class="section-header">
|
||
<div>
|
||
<h6>2. Controlli di produzione</h6>
|
||
<p class="section-hint mb-0">Istruzioni e frequenze di controllo per l’operatore</p>
|
||
</div>
|
||
<div class="soft-badge">Sezione operativa</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="row g-3">
|
||
<div class="col-12">
|
||
<label class="form-label">Impostazione misure controllo produzione</label>
|
||
<textarea class="form-control" name="prod_control_measure_settings" rows="3"><?= $worksheet ? h($worksheet['prod_control_measure_settings']) : '' ?></textarea>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Controlli - Taglio</label>
|
||
<select class="form-select" name="control_frequency_cut" id="control_frequency_cut">
|
||
<?= ws_options($lookup['control_frequency_cut'] ?? [], $worksheet['control_frequency_cut'] ?? '', $lookupDefault['control_frequency_cut'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Controlli - Disegno</label>
|
||
<select class="form-select" name="control_frequency_drawing" id="control_frequency_drawing">
|
||
<?= ws_options($lookup['control_frequency_drawing'] ?? [], $worksheet['control_frequency_drawing'] ?? '', $lookupDefault['control_frequency_drawing'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Controlli - Dima</label>
|
||
<select class="form-select" name="control_frequency_jig" id="control_frequency_jig">
|
||
<?= ws_options($lookup['control_frequency_jig'] ?? [], $worksheet['control_frequency_jig'] ?? '', $lookupDefault['control_frequency_jig'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Modalità dima</label>
|
||
<select class="form-select" name="control_mode_jig" id="control_mode_jig">
|
||
<?= ws_options($lookup['control_mode_jig'] ?? [], $worksheet['control_mode_jig'] ?? '', $lookupDefault['control_mode_jig'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-block theme-orange">
|
||
<div class="section-header">
|
||
<div>
|
||
<h6>3. Imballo e confezionamento</h6>
|
||
<p class="section-hint mb-0">Dati per confezione, scatola e bancale</p>
|
||
</div>
|
||
<div class="soft-badge">Packaging</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="section-grid-note">Compila prima la confezione, poi eventuali dettagli di scatola e bancale</div>
|
||
|
||
<div class="row g-3">
|
||
<div class="col-lg-4">
|
||
<label class="form-label">Codice confezione</label>
|
||
<select class="form-select" name="requested_package_code" id="requested_package_code">
|
||
<?= packaging_options($packagingLookup['PACKAGING_TYPE'] ?? [], $worksheet['requested_package_code'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-4 col-md-6">
|
||
<label class="form-label">Metri per confezione</label>
|
||
<input type="number" class="form-control" name="meters_per_package"
|
||
value="<?= $worksheet ? h($worksheet['meters_per_package']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-4 col-md-6">
|
||
<label class="form-label">Tolleranza metri/confezione</label>
|
||
<input type="text" class="form-control" name="meters_per_package_tolerance"
|
||
value="<?= $worksheet ? h($worksheet['meters_per_package_tolerance']) : '' ?>"
|
||
placeholder="es. +/- 4m">
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<label class="form-label">Note metri/confezione</label>
|
||
<input type="text" class="form-control" name="meters_per_package_notes"
|
||
value="<?= $worksheet ? h($worksheet['meters_per_package_notes']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Scatola (tipo)</label>
|
||
<select class="form-select" name="box_type" id="box_type">
|
||
<?= packaging_options($packagingLookup['BOX'] ?? [], $worksheet['box_type'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">N° conf./pezzi per scatola</label>
|
||
<input type="number" class="form-control" name="packages_or_pieces_per_box"
|
||
value="<?= $worksheet ? h($worksheet['packages_or_pieces_per_box']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Metri per scatola</label>
|
||
<input type="number" class="form-control" name="meters_per_box"
|
||
value="<?= $worksheet ? h($worksheet['meters_per_box']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Bancale (tipo)</label>
|
||
<select class="form-select" name="pallet_type" id="pallet_type">
|
||
<?= packaging_options($packagingLookup['PALLET'] ?? [], $worksheet['pallet_type'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Scatole/conf. per bancale</label>
|
||
<input type="number" class="form-control" name="boxes_or_packages_per_pallet"
|
||
value="<?= $worksheet ? h($worksheet['boxes_or_packages_per_pallet']) : '' ?>">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-block theme-purple">
|
||
<div class="section-header">
|
||
<div>
|
||
<h6>4. Velocità di produzione</h6>
|
||
<p class="section-hint mb-0">Confronto tra velocità prevista ed effettiva</p>
|
||
</div>
|
||
<div class="soft-badge">Prestazioni linea</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="row g-3">
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Vel. prevista (kg/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_expected_kg_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_expected_kg_h']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Vel. effettiva (kg/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_actual_kg_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_actual_kg_h']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Vel. prevista (m/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_expected_m_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_expected_m_h']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-lg-3 col-md-6">
|
||
<label class="form-label">Vel. effettiva (m/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_actual_m_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_actual_m_h']) : '' ?>">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-block theme-gray">
|
||
<div class="section-header">
|
||
<div>
|
||
<h6>5. Note finali</h6>
|
||
<p class="section-hint mb-0">Annotazioni operative o indicazioni aggiuntive</p>
|
||
</div>
|
||
<div class="soft-badge">Facoltativo</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="row g-3">
|
||
<div class="col-12">
|
||
<label class="form-label">Note</label>
|
||
<textarea class="form-control" name="notes" rows="3"><?= $worksheet ? h($worksheet['notes']) : '' ?></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="action-bar">
|
||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center gap-3">
|
||
<div>
|
||
<div class="fw-bold text-dark">Flusso consigliato</div>
|
||
<div class="text-muted small">1. Compila la testata → 2. Salva → 3. Aggiungi una o più mescole</div>
|
||
</div>
|
||
<div class="d-flex gap-2 flex-wrap">
|
||
<button type="submit" class="btn btn-main-save">💾 Salva testata</button>
|
||
<button type="button" class="btn btn-mix"
|
||
id="btnAddMix" data-bs-toggle="modal" data-bs-target="#mixModal" disabled>
|
||
➕ Aggiungi mescola
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<div class="section-block theme-cyan mt-4 mb-0">
|
||
<div class="section-header">
|
||
<div>
|
||
<h6>6. Mescole associate al foglio</h6>
|
||
<p class="section-hint mb-0">Inserisci una o più righe mescola dopo il salvataggio della testata</p>
|
||
</div>
|
||
<div class="mini-pill"><?= count($mixRows) ?> righe</div>
|
||
</div>
|
||
<div class="section-body">
|
||
<div class="mix-table-title">
|
||
<div>
|
||
<h5>Elenco mescole</h5>
|
||
<div class="mix-helper">Puoi modificare o eliminare ogni riga direttamente dalla tabella</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="table-wrap">
|
||
<div class="table-responsive">
|
||
<table id="tabellaMixRows" class="table table-striped table-bordered mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:70px;">Pos</th>
|
||
<th>Mescola</th>
|
||
<th style="width:120px;">Peso (g/m)</th>
|
||
<th style="width:140px;">Densità</th>
|
||
<th style="width:150px;">Durezza</th>
|
||
<th style="width:120px;">Lubr.</th>
|
||
<th style="width:170px;">Azioni</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($mixRows as $r): ?>
|
||
<tr>
|
||
<td><?= (int)$r['mix_position'] ?></td>
|
||
<td>
|
||
<div class="fw-bold"><?= h($r['mescola_nome'] ?? '-') ?></div>
|
||
<?php if (!empty($r['mescola_uscita'])): ?>
|
||
<div class="text-muted small"><?= h($r['mescola_uscita']) ?></div>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td><?= h($r['mix_weight_g_m'] ?? '-') ?></td>
|
||
<td><?= h($r['required_density'] ?? '-') ?></td>
|
||
<td><?= h($r['required_hardness_shore_a'] ?? '-') ?></td>
|
||
<td><?= h($r['lubrication_type'] ?? '-') ?></td>
|
||
<td class="text-nowrap">
|
||
<button class="btn btn-sm btn-outline-primary edit-mix"
|
||
data-row='<?= h(json_encode($r, JSON_UNESCAPED_UNICODE)) ?>'>
|
||
✏️ Modifica
|
||
</button>
|
||
<button class="btn btn-sm btn-outline-danger delete-mix"
|
||
data-id="<?= (int)$r['id'] ?>">
|
||
🗑️
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<?php include('include/footer.php'); ?>
|
||
</div>
|
||
|
||
<!-- MODAL MIX -->
|
||
<div class="modal fade" id="mixModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header mix-modal-head">
|
||
<div>
|
||
<h5 class="modal-title mb-1" id="mixModalTitle">Aggiungi Mescola</h5>
|
||
<div class="small">Compila i dati della mescola da associare al foglio</div>
|
||
</div>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="mixForm">
|
||
<input type="hidden" name="worksheet_id" id="mixWorksheetId" value="<?= (int)$worksheet_id ?>">
|
||
<input type="hidden" name="row_id" id="mixRowId" value="0">
|
||
<input type="hidden" name="mix_position" id="mix_position" value="">
|
||
|
||
<div class="row g-3">
|
||
<div class="col-lg-8">
|
||
<label class="form-label">Mescola *</label>
|
||
<select class="form-select" name="idmescola" id="idmescola" required>
|
||
<option value="">-- Seleziona --</option>
|
||
<?php foreach ($mescole as $me): ?>
|
||
<option value="<?= (int)$me['id'] ?>">
|
||
<?= h($me['nome']) ?><?= $me['nomeuscita'] ? ' — ' . h($me['nomeuscita']) : '' ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-lg-4">
|
||
<label class="form-label">Peso metro mescola (g/m)</label>
|
||
<input type="number" step="0.01" class="form-control" name="mix_weight_g_m" id="mix_weight_g_m">
|
||
</div>
|
||
|
||
<div class="col-lg-4">
|
||
<label class="form-label">Densità richiesta</label>
|
||
<input type="text" class="form-control" name="required_density" id="required_density" placeholder="es. 1,22 +/- 0,03">
|
||
</div>
|
||
|
||
<div class="col-lg-4">
|
||
<label class="form-label">Durezza richiesta (shore A)</label>
|
||
<input type="text" class="form-control" name="required_hardness_shore_a" id="required_hardness_shore_a" placeholder="es. 70 +/- 5">
|
||
</div>
|
||
|
||
<div class="col-lg-4">
|
||
<label class="form-label">Lubrificazione</label>
|
||
<select class="form-select" name="lubrication_type" id="lubrication_type">
|
||
<?= ws_options($lookup['lubrication_type'] ?? [], '', $lookupDefault['lubrication_type'] ?? '') ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<label class="form-label">Note lubrificazione</label>
|
||
<input type="text" class="form-control" name="lubrication_notes" id="lubrication_notes">
|
||
</div>
|
||
|
||
<div class="col-12 text-center mt-2">
|
||
<button type="submit" class="btn btn-main-save">💾 Salva mescola</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php include('jsinclude.php'); ?>
|
||
|
||
<script>
|
||
$(document).ready(function() {
|
||
const wsIdInput = $('#wsId');
|
||
const btnAddMix = $('#btnAddMix');
|
||
const summaryWsId = $('#summaryWsId');
|
||
|
||
if ($('#idmatrice').length) {
|
||
$('#idmatrice').select2({
|
||
theme: 'bootstrap4',
|
||
width: '100%',
|
||
placeholder: '-- Seleziona --',
|
||
allowClear: true
|
||
});
|
||
}
|
||
|
||
$('#mixModal').on('shown.bs.modal', function() {
|
||
if (!$('#idmescola').data('select2')) {
|
||
$('#idmescola').select2({
|
||
theme: 'bootstrap4',
|
||
width: '100%',
|
||
dropdownParent: $('#mixModal'),
|
||
placeholder: '-- Seleziona --',
|
||
allowClear: true
|
||
});
|
||
}
|
||
});
|
||
|
||
function enableMixButtonIfSaved() {
|
||
const id = parseInt(wsIdInput.val() || '0', 10);
|
||
if (id > 0) {
|
||
btnAddMix.prop('disabled', false);
|
||
$('#mixWorksheetId').val(id);
|
||
|
||
if (!summaryWsId.text().trim()) {
|
||
summaryWsId.text('Assegnato');
|
||
}
|
||
} else {
|
||
btnAddMix.prop('disabled', true);
|
||
$('#mixWorksheetId').val('0');
|
||
summaryWsId.text('Non assegnato');
|
||
}
|
||
}
|
||
enableMixButtonIfSaved();
|
||
|
||
$('#tabellaMixRows').DataTable({
|
||
pageLength: 25,
|
||
lengthMenu: [10, 25, 50, 100],
|
||
order: [
|
||
[0, 'asc']
|
||
],
|
||
language: {
|
||
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json'
|
||
}
|
||
});
|
||
|
||
// Save header
|
||
$('#worksheetHeaderForm').on('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const formData = new FormData(this);
|
||
formData.append('ajax', '1');
|
||
formData.append('action', 'save_header');
|
||
|
||
fetch(window.location.href, {
|
||
method: 'POST',
|
||
body: new URLSearchParams(formData)
|
||
})
|
||
.then(async (r) => {
|
||
const text = await r.text();
|
||
try {
|
||
return JSON.parse(text);
|
||
} catch (err) {
|
||
console.error('Response is not valid JSON:', text);
|
||
throw new Error('Risposta non JSON (vedi console)');
|
||
}
|
||
})
|
||
.then(data => {
|
||
if (!data.success) {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore',
|
||
text: data.message
|
||
});
|
||
return;
|
||
}
|
||
|
||
wsIdInput.val(data.id);
|
||
|
||
if (data.worksheet_number_label) {
|
||
summaryWsId.text(data.worksheet_number_label);
|
||
}
|
||
|
||
enableMixButtonIfSaved();
|
||
|
||
if (!window.location.search.includes('id=')) {
|
||
const newUrl = 'manage-worksheet.php?id=' + data.id;
|
||
window.history.replaceState({}, '', newUrl);
|
||
}
|
||
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Testata salvata',
|
||
text: (data.worksheet_number_label ? ('Foglio ' + data.worksheet_number_label + ' creato correttamente. Vuoi aggiungere subito le mescole?') : 'Vuoi aggiungere subito le mescole?'),
|
||
showCancelButton: true,
|
||
confirmButtonText: 'Sì, aggiungi mescole',
|
||
cancelButtonText: 'No'
|
||
}).then(res => {
|
||
if (res.isConfirmed) {
|
||
const modal = new bootstrap.Modal(document.getElementById('mixModal'));
|
||
modal.show();
|
||
}
|
||
});
|
||
})
|
||
.catch(err => {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore AJAX',
|
||
text: err.message
|
||
});
|
||
});
|
||
});
|
||
|
||
// Prepare modal for add
|
||
$('#mixModal').on('show.bs.modal', function() {
|
||
const wsId = parseInt(wsIdInput.val() || '0', 10);
|
||
if (wsId <= 0) {
|
||
Swal.fire({
|
||
icon: 'warning',
|
||
title: 'Salva prima la testata',
|
||
timer: 1200
|
||
});
|
||
return false;
|
||
}
|
||
|
||
$('#mixModalTitle').text('Aggiungi Mescola');
|
||
$('#mixForm')[0].reset();
|
||
$('#mixRowId').val('0');
|
||
$('#mixWorksheetId').val(wsId);
|
||
$('#idmescola').prop('disabled', false).val('').trigger('change');
|
||
$('#lubrication_type').val('');
|
||
});
|
||
|
||
// Edit mix row
|
||
$(document).on('click', '.edit-mix', function() {
|
||
let row = $(this).attr('data-row');
|
||
row = JSON.parse(row);
|
||
|
||
$('#mixModalTitle').text('Modifica Mescola');
|
||
$('#mixForm')[0].reset();
|
||
|
||
$('#mixRowId').val(row.id);
|
||
$('#mixWorksheetId').val(row.worksheet_id);
|
||
|
||
$('#idmescola').prop('disabled', false);
|
||
$('#idmescola').val(row.idmescola).trigger('change');
|
||
|
||
$('#mix_weight_g_m').val(row.mix_weight_g_m ?? '');
|
||
$('#required_density').val(row.required_density ?? '');
|
||
$('#required_hardness_shore_a').val(row.required_hardness_shore_a ?? '');
|
||
$('#lubrication_type').val(row.lubrication_type ?? '');
|
||
$('#lubrication_notes').val(row.lubrication_notes ?? '');
|
||
|
||
const modal = new bootstrap.Modal(document.getElementById('mixModal'));
|
||
modal.show();
|
||
});
|
||
|
||
// Save mix row
|
||
$('#mixForm').on('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const formData = new FormData(this);
|
||
formData.append('ajax', '1');
|
||
formData.append('action', 'save_mix_row');
|
||
|
||
fetch('', {
|
||
method: 'POST',
|
||
body: new URLSearchParams(formData)
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Salvata!',
|
||
timer: 800
|
||
}).then(() => location.reload());
|
||
} else {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore',
|
||
text: data.message
|
||
});
|
||
}
|
||
});
|
||
});
|
||
|
||
// Delete mix row
|
||
$(document).on('click', '.delete-mix', function() {
|
||
const rowId = $(this).data('id');
|
||
|
||
Swal.fire({
|
||
title: 'Eliminare questa mescola dal foglio?',
|
||
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_mix_row&row_id=${rowId}`
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Eliminata!',
|
||
timer: 800
|
||
}).then(() => location.reload());
|
||
} else {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore',
|
||
text: data.message
|
||
});
|
||
}
|
||
});
|
||
});
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|