887 lines
32 KiB
PHP
887 lines
32 KiB
PHP
<?php
|
|
// Debug
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
error_reporting(E_ALL);
|
|
ini_set('log_errors', 1);
|
|
ini_set('error_log', __DIR__ . '/quotations_debug.log');
|
|
|
|
if (!file_exists(__DIR__ . '/quotations_debug.log')) {
|
|
file_put_contents(__DIR__ . '/quotations_debug.log', "Inizio operazioni alle " . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
|
|
}
|
|
|
|
error_log("Inizio operazioni alle " . date('Y-m-d H:i:s'));
|
|
|
|
include('include/headscript.php');
|
|
|
|
$db = DBHandlerSelect::getInstance();
|
|
$pdo = $db->getConnection();
|
|
|
|
$user_id = $iduserlogin ?? 1;
|
|
|
|
/**
|
|
* Helper redirect
|
|
*/
|
|
function redirectWithMessage($status, $message, $extraQuery = '')
|
|
{
|
|
$url = 'quotations.php?status=' . urlencode($status) . '&message=' . urlencode($message);
|
|
|
|
if ($extraQuery !== '') {
|
|
$url .= '&' . ltrim($extraQuery, '&');
|
|
}
|
|
|
|
header("Location: " . $url);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* CREATE quotation
|
|
* Ora description e customer vengono salvati subito dal modale.
|
|
*/
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'create') {
|
|
$description = trim($_POST['description'] ?? '');
|
|
$customer = trim($_POST['customer'] ?? '');
|
|
|
|
if ($description === '' || $customer === '') {
|
|
redirectWithMessage('error', 'Descrizione e Cliente sono obbligatori');
|
|
}
|
|
|
|
try {
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO quotations
|
|
(description, customer, iduser)
|
|
VALUES
|
|
(?, ?, ?)
|
|
");
|
|
|
|
$success = $stmt->execute([
|
|
$description,
|
|
$customer,
|
|
$user_id
|
|
]);
|
|
|
|
if ($success) {
|
|
$newId = $pdo->lastInsertId();
|
|
error_log("Creata nuova quotation ID: " . $newId);
|
|
|
|
redirectWithMessage('success', 'Quotation creata con successo');
|
|
}
|
|
|
|
error_log("Errore: impossibile creare la quotation");
|
|
redirectWithMessage('error', 'Errore durante la creazione della quotation');
|
|
} catch (PDOException $e) {
|
|
error_log("Errore PDO durante la creazione della quotation: " . $e->getMessage());
|
|
redirectWithMessage('error', 'Errore database: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* UPDATE quotation
|
|
* Gestisce sia form normale sia salvataggio inline AJAX.
|
|
*/
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'update' && isset($_POST['id'])) {
|
|
$id = intval($_POST['id']);
|
|
$description = trim($_POST['description'] ?? '');
|
|
$customer = trim($_POST['customer'] ?? '');
|
|
$isAjax = isset($_POST['ajax']) && $_POST['ajax'] === '1';
|
|
|
|
if ($description === '' || $customer === '') {
|
|
if ($isAjax) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode([
|
|
'success' => false,
|
|
'message' => 'Descrizione e Cliente sono obbligatori'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
redirectWithMessage('error', 'Descrizione e Cliente sono obbligatori');
|
|
}
|
|
|
|
try {
|
|
$stmt = $pdo->prepare("
|
|
UPDATE quotations
|
|
SET description = ?, customer = ?
|
|
WHERE id = ? AND iduser = ?
|
|
");
|
|
|
|
$stmt->execute([
|
|
$description,
|
|
$customer,
|
|
$id,
|
|
$user_id
|
|
]);
|
|
|
|
error_log("Modificata quotation ID: " . $id);
|
|
|
|
if ($isAjax) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode([
|
|
'success' => true,
|
|
'message' => 'Quotation modificata con successo'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
redirectWithMessage('success', 'Quotation modificata con successo');
|
|
} catch (PDOException $e) {
|
|
error_log("Errore PDO durante la modifica della quotation: " . $e->getMessage());
|
|
|
|
if ($isAjax) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode([
|
|
'success' => false,
|
|
'message' => 'Errore database: ' . $e->getMessage()
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
redirectWithMessage('error', 'Errore database: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DELETE quotation
|
|
*/
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delete' && isset($_POST['id'])) {
|
|
$id = intval($_POST['id']);
|
|
|
|
try {
|
|
$stmt = $pdo->prepare("
|
|
DELETE FROM quotations
|
|
WHERE id = ? AND iduser = ?
|
|
");
|
|
|
|
$stmt->execute([
|
|
$id,
|
|
$user_id
|
|
]);
|
|
|
|
error_log("Cancellata quotation ID: " . $id);
|
|
|
|
redirectWithMessage('success', 'Quotation cancellata con successo');
|
|
} catch (PDOException $e) {
|
|
error_log("Errore PDO durante la cancellazione della quotation: " . $e->getMessage());
|
|
redirectWithMessage('error', 'Errore database: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recupera tutte le quotations dell'utente.
|
|
* Ultima creata in alto.
|
|
*/
|
|
try {
|
|
$stmt = $pdo->prepare("
|
|
SELECT *
|
|
FROM quotations
|
|
WHERE iduser = ?
|
|
ORDER BY creation_date DESC, id DESC
|
|
");
|
|
|
|
$stmt->execute([
|
|
$user_id
|
|
]);
|
|
|
|
$quotations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
error_log("Errore PDO durante il recupero delle quotations: " . $e->getMessage());
|
|
$quotations = [];
|
|
}
|
|
|
|
/**
|
|
* Recupera quotation in modifica dettagliata
|
|
*/
|
|
$editQuotation = null;
|
|
|
|
if (isset($_GET['edit_id'])) {
|
|
$editId = intval($_GET['edit_id']);
|
|
|
|
try {
|
|
$stmt = $pdo->prepare("
|
|
SELECT *
|
|
FROM quotations
|
|
WHERE id = ? AND iduser = ?
|
|
");
|
|
|
|
$stmt->execute([
|
|
$editId,
|
|
$user_id
|
|
]);
|
|
|
|
$editQuotation = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$editQuotation) {
|
|
error_log("Nessuna quotation trovata per id: " . $editId);
|
|
}
|
|
} catch (PDOException $e) {
|
|
error_log("Errore PDO durante il recupero della quotation per modifica: " . $e->getMessage());
|
|
$editQuotation = null;
|
|
}
|
|
}
|
|
?>
|
|
|
|
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
|
|
|
<?php include('cssinclude.php'); ?>
|
|
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
|
|
|
|
<style>
|
|
.cell-changed {
|
|
background-color: #fff3b0 !important;
|
|
transition: background-color 0.3s ease;
|
|
}
|
|
|
|
input.manual-input,
|
|
select.manual-input,
|
|
textarea.manual-input {
|
|
background-color: #fff3cd;
|
|
}
|
|
|
|
input.required-input,
|
|
select.required-input,
|
|
textarea.required-input {
|
|
background-color: #f8d7da;
|
|
}
|
|
|
|
input,
|
|
select,
|
|
textarea {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
border: 1px solid #ced4da;
|
|
border-radius: 4px;
|
|
padding: 5px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
textarea {
|
|
resize: vertical;
|
|
}
|
|
|
|
.action-btn {
|
|
padding: 6px 8px;
|
|
margin-right: 5px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
width: 35px;
|
|
height: 35px;
|
|
box-sizing: border-box;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.save-btn {
|
|
background-color: #28a745;
|
|
color: white;
|
|
}
|
|
|
|
.delete-btn {
|
|
background-color: #dc3545;
|
|
color: white;
|
|
}
|
|
|
|
.photos-btn {
|
|
background-color: #007bff;
|
|
color: white;
|
|
}
|
|
|
|
.parts-btn {
|
|
background-color: #ffc107;
|
|
color: #212529;
|
|
}
|
|
|
|
.edit-detail-btn {
|
|
background-color: #6c757d;
|
|
color: white;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.form-group label {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.form-group textarea {
|
|
min-height: 100px;
|
|
}
|
|
|
|
.flash-success {
|
|
background-color: #d4edda !important;
|
|
transition: background-color 0.3s ease;
|
|
}
|
|
|
|
.quotation-actions {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.modal.fade {
|
|
z-index: 1060 !important;
|
|
}
|
|
|
|
.modal-backdrop {
|
|
z-index: 1055 !important;
|
|
}
|
|
|
|
.overlay.toggle-icon {
|
|
z-index: 1000 !important;
|
|
}
|
|
|
|
.alert {
|
|
margin-bottom: 15px;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.alert-success {
|
|
background-color: #d4edda;
|
|
color: #155724;
|
|
border: 1px solid #c3e6cb;
|
|
}
|
|
|
|
.alert-danger {
|
|
background-color: #f8d7da;
|
|
color: #721c24;
|
|
border: 1px solid #f5c6cb;
|
|
}
|
|
|
|
#quotationsTable textarea {
|
|
min-height: 60px;
|
|
}
|
|
|
|
.modal-body textarea {
|
|
min-height: 120px;
|
|
}
|
|
|
|
/* =========================================================
|
|
FIX PHOTOS MODAL
|
|
The photos modal used by photos.js is not a standard Bootstrap modal.
|
|
Without this scoped CSS it can appear full screen.
|
|
========================================================= */
|
|
|
|
#photosModal,
|
|
#photoModal,
|
|
#imageModal,
|
|
#annotationsModal {
|
|
display: none;
|
|
position: fixed;
|
|
z-index: 1070 !important;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: auto;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
#photosModal .modal-content,
|
|
#photoModal .modal-content,
|
|
#imageModal .modal-content,
|
|
#annotationsModal .modal-content {
|
|
background-color: #ffffff;
|
|
margin: 5% auto;
|
|
padding: 20px;
|
|
border: 1px solid #888;
|
|
width: 90%;
|
|
max-width: 900px;
|
|
border-radius: 8px;
|
|
position: relative;
|
|
}
|
|
|
|
/* If the modal contains images/canvas, avoid overflow */
|
|
#photosModal img,
|
|
#photoModal img,
|
|
#imageModal img,
|
|
#annotationsModal img,
|
|
#photosModal canvas,
|
|
#photoModal canvas,
|
|
#imageModal canvas,
|
|
#annotationsModal canvas {
|
|
max-width: 100%;
|
|
height: auto;
|
|
}
|
|
|
|
/* Close button used by custom photo modal */
|
|
#photosModal .close-btn,
|
|
#photoModal .close-btn,
|
|
#imageModal .close-btn,
|
|
#annotationsModal .close-btn {
|
|
color: #aaa;
|
|
float: right;
|
|
font-size: 28px;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
}
|
|
|
|
#photosModal .close-btn:hover,
|
|
#photoModal .close-btn:hover,
|
|
#imageModal .close-btn:hover,
|
|
#annotationsModal .close-btn:hover {
|
|
color: #000;
|
|
}
|
|
</style>
|
|
|
|
<title>Gestione Quotations - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<?php include('include/topbar.php'); ?>
|
|
|
|
<div class="page-wrapper">
|
|
<div class="page-content">
|
|
<div class="card radius-10">
|
|
<div class="card-header">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<h6 class="mb-0">Gestione Quotations</h6>
|
|
</div>
|
|
|
|
<?php if (!$editQuotation): ?>
|
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createModal">
|
|
<i class="fas fa-plus me-1"></i> Crea Nuova Quotation
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<?php if (isset($_GET['status']) && isset($_GET['message'])): ?>
|
|
<div class="alert alert-<?= $_GET['status'] === 'success' ? 'success' : 'danger' ?> temp-alert">
|
|
<?= htmlspecialchars(urldecode($_GET['message']), ENT_QUOTES, 'UTF-8') ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($editQuotation): ?>
|
|
|
|
<h6 class="mb-3">
|
|
Modifica Quotation ID: <?= htmlspecialchars($editQuotation['id'], ENT_QUOTES, 'UTF-8') ?>
|
|
</h6>
|
|
|
|
<form id="editForm" method="post" action="quotations.php">
|
|
<input type="hidden" name="action" value="update">
|
|
<input type="hidden" name="id" value="<?= htmlspecialchars($editQuotation['id'], ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
<div class="form-group">
|
|
<label for="description">Descrizione</label>
|
|
<textarea
|
|
id="description"
|
|
name="description"
|
|
class="manual-input required-input"
|
|
required><?= htmlspecialchars($editQuotation['description'] ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="customer">Cliente</label>
|
|
<input
|
|
type="text"
|
|
id="customer"
|
|
name="customer"
|
|
class="manual-input required-input"
|
|
value="<?= htmlspecialchars($editQuotation['customer'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
|
|
required>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary">
|
|
Salva Modifiche
|
|
</button>
|
|
|
|
<a href="quotations.php" class="btn btn-secondary">
|
|
Torna alla Lista
|
|
</a>
|
|
</form>
|
|
|
|
<div class="quotation-actions">
|
|
<h6 class="mb-3">Azioni</h6>
|
|
|
|
<button
|
|
type="button"
|
|
class="photos-btn action-btn"
|
|
data-entity-type="quotation"
|
|
data-row="0"
|
|
data-idquotations="<?= htmlspecialchars($editQuotation['id'], ENT_QUOTES, 'UTF-8') ?>"
|
|
title="Photos">
|
|
<i class="fas fa-camera"></i>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="parts-btn action-btn"
|
|
data-entity-type="quotation"
|
|
data-iddatadb=""
|
|
data-idquotations="<?= htmlspecialchars($editQuotation['id'], ENT_QUOTES, 'UTF-8') ?>"
|
|
data-row="0"
|
|
title="Parts">
|
|
<i class="fas fa-puzzle-piece"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<?php else: ?>
|
|
|
|
<h6 class="mb-3">Quotations Esistenti</h6>
|
|
|
|
<table id="quotationsTable" class="table table-striped table-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Data Creazione</th>
|
|
<th>Descrizione</th>
|
|
<th>Cliente</th>
|
|
<th>Azioni</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<?php foreach ($quotations as $index => $row): ?>
|
|
<tr data-id="<?= htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8') ?>">
|
|
<td><?= htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8') ?></td>
|
|
|
|
<td><?= htmlspecialchars($row['creation_date'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
|
|
|
|
<td>
|
|
<textarea
|
|
name="description"
|
|
class="cell-input manual-input form-control"
|
|
required><?= htmlspecialchars($row['description'] ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
|
|
</td>
|
|
|
|
<td>
|
|
<input
|
|
type="text"
|
|
name="customer"
|
|
class="cell-input manual-input form-control"
|
|
value="<?= htmlspecialchars($row['customer'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
|
|
required>
|
|
</td>
|
|
|
|
<td>
|
|
<button
|
|
type="button"
|
|
class="save-btn action-btn edit-btn"
|
|
data-id="<?= htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8') ?>"
|
|
title="Salva Modifiche">
|
|
<i class="fas fa-save"></i>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="delete-btn action-btn"
|
|
data-id="<?= htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8') ?>"
|
|
title="Cancella"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#deleteModal">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="photos-btn action-btn"
|
|
data-entity-type="quotation"
|
|
data-idquotations="<?= htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8') ?>"
|
|
data-row="<?= htmlspecialchars($index, ENT_QUOTES, 'UTF-8') ?>"
|
|
title="Photos">
|
|
<i class="fas fa-camera"></i>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="parts-btn action-btn"
|
|
data-entity-type="quotation"
|
|
data-idquotations="<?= htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8') ?>"
|
|
data-row="<?= htmlspecialchars($index, ENT_QUOTES, 'UTF-8') ?>"
|
|
title="Parts">
|
|
<i class="fas fa-puzzle-piece"></i>
|
|
</button>
|
|
|
|
<a
|
|
href="quotations.php?edit_id=<?= urlencode($row['id']) ?>"
|
|
class="edit-detail-btn action-btn"
|
|
title="Modifica Dettagliata">
|
|
<i class="fas fa-edit"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal creazione nuova quotation -->
|
|
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="createModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
|
|
<form id="createModalForm" method="post" action="quotations.php">
|
|
<input type="hidden" name="action" value="create">
|
|
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="createModalLabel">
|
|
Crea Nuova Quotation
|
|
</h5>
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="create_description">Descrizione</label>
|
|
<textarea
|
|
id="create_description"
|
|
name="description"
|
|
class="manual-input required-input"
|
|
required
|
|
placeholder="Inserisci la descrizione della quotation"></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="create_customer">Cliente</label>
|
|
<input
|
|
type="text"
|
|
id="create_customer"
|
|
name="customer"
|
|
class="manual-input required-input"
|
|
required
|
|
placeholder="Inserisci il nome del cliente">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
|
Annulla
|
|
</button>
|
|
|
|
<button type="submit" class="btn btn-primary">
|
|
Crea Quotation
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal cancellazione quotation -->
|
|
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
|
|
<form id="deleteForm" method="post" action="quotations.php">
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="id" id="deleteQuotationId">
|
|
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteModalLabel">
|
|
Conferma Cancellazione
|
|
</h5>
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<p>Sicuro di voler cancellare questa quotation?</p>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
|
Annulla
|
|
</button>
|
|
|
|
<button type="submit" class="btn btn-danger">
|
|
Conferma
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overlay toggle-icon"></div>
|
|
|
|
<a href="javaScript:;" class="back-to-top">
|
|
<i class='bx bxs-up-arrow-alt'></i>
|
|
</a>
|
|
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
|
|
<div id="partsModalContainer"></div>
|
|
<div id="annotationsModalContainer"></div>
|
|
|
|
<?php include 'photos_functions.php'; ?>
|
|
|
|
<?php include('jsinclude.php'); ?>
|
|
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
|
|
|
|
<script src="photos.js"></script>
|
|
<script src="annotationsModal.js"></script>
|
|
<script src="partsTable.js"></script>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
|
|
// Rimuove automaticamente gli alert dopo 5 secondi
|
|
setTimeout(function() {
|
|
document.querySelectorAll('.temp-alert').forEach(function(el) {
|
|
el.remove();
|
|
});
|
|
}, 5000);
|
|
|
|
// Inizializza DataTables solo nella lista
|
|
if (!document.querySelector('#editForm') && document.querySelector('#quotationsTable')) {
|
|
$('#quotationsTable').DataTable({
|
|
paging: true,
|
|
searching: true,
|
|
ordering: true,
|
|
info: true,
|
|
autoWidth: false,
|
|
responsive: true,
|
|
order: [
|
|
[1, 'desc'],
|
|
[0, 'desc']
|
|
]
|
|
});
|
|
}
|
|
|
|
// Nasconde overlay template quando si apre il modal create
|
|
$('#createModal').on('show.bs.modal', function() {
|
|
$('.overlay.toggle-icon').css('display', 'none');
|
|
});
|
|
|
|
$('#createModal').on('hide.bs.modal', function() {
|
|
$('.overlay.toggle-icon').css('display', '');
|
|
});
|
|
|
|
// Apertura modal Parts
|
|
$(document).on('click', '.parts-btn', function() {
|
|
const idquotations = $(this).data('idquotations');
|
|
|
|
if (!idquotations) {
|
|
alert('ID quotation mancante.');
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: 'modal_partsTable.php',
|
|
method: 'GET',
|
|
data: {
|
|
idquotations: idquotations
|
|
},
|
|
success: function(response) {
|
|
$('#partsModalContainer').html(response);
|
|
|
|
const modalElement = document.getElementById('partsModal');
|
|
if (!modalElement) {
|
|
alert('Modale parts non trovato.');
|
|
return;
|
|
}
|
|
|
|
$("#trfHeader").text(`Quotation #${idquotations}`);
|
|
$("#partsModal").data("idquotations", idquotations);
|
|
|
|
let modal = bootstrap.Modal.getInstance(modalElement) || new bootstrap.Modal(modalElement, {
|
|
backdrop: true
|
|
});
|
|
|
|
modal.show();
|
|
|
|
if (typeof window.loadParts === 'function') {
|
|
window.loadParts(null, idquotations);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
alert('Errore nel caricamento del modale: ' + error);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Pulizia modal dinamici
|
|
$(document).on('hidden.bs.modal', '#partsModal', function() {
|
|
$('#partsModalContainer').empty();
|
|
$('.modal-backdrop').remove();
|
|
$('body').removeClass('modal-open').css('padding-right', '');
|
|
});
|
|
|
|
$(document).on('hidden.bs.modal', '#annotationsModal', function() {
|
|
$('#annotationsModalContainer').empty();
|
|
$('.modal-backdrop').remove();
|
|
$('body').removeClass('modal-open').css('padding-right', '');
|
|
});
|
|
|
|
// Salvataggio inline
|
|
$(document).on('click', '.edit-btn', function() {
|
|
const row = this.closest('tr');
|
|
const id = row.dataset.id;
|
|
const description = row.querySelector('textarea[name="description"]').value.trim();
|
|
const customer = row.querySelector('input[name="customer"]').value.trim();
|
|
|
|
if (!description || !customer) {
|
|
alert('Descrizione e Cliente sono obbligatori.');
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append('action', 'update');
|
|
formData.append('ajax', '1');
|
|
formData.append('id', id);
|
|
formData.append('description', description);
|
|
formData.append('customer', customer);
|
|
|
|
fetch('quotations.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
row.classList.add('flash-success');
|
|
setTimeout(() => row.classList.remove('flash-success'), 700);
|
|
} else {
|
|
alert(data.message || 'Errore durante la modifica.');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Errore durante la modifica della quotation:', error);
|
|
alert('Errore durante la modifica: ' + error.message);
|
|
});
|
|
});
|
|
|
|
// Imposta ID da cancellare nel modal
|
|
$(document).on('click', '.delete-btn', function() {
|
|
const id = this.dataset.id;
|
|
document.getElementById('deleteQuotationId').value = id;
|
|
});
|
|
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|