added files for mescole
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
<?php include('include/headscript.php'); ?>
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<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'); ?>
|
||||
<title>Scheda Mescola - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></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>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-size: 1.05rem;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.back-dashboard {
|
||||
background-color: #cfe3ff !important;
|
||||
color: #1f2d3d !important;
|
||||
border: 1px solid #bcd4f4 !important;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
padding: 10px 18px;
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.back-dashboard:hover {
|
||||
background-color: #b9d3ff !important;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: .8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .04em;
|
||||
color: #6c757d;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
background-color: #cfe3ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-add:hover {
|
||||
background-color: #0b5ed7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper" id="appWrapper">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
|
||||
<!-- HEADER INFO GENERALI -->
|
||||
<div class="card p-3 mb-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0" id="hNomeUscita">Scheda Mescola</h5>
|
||||
<button type="button" class="btn back-dashboard" onclick="location.href='mescole.php'">
|
||||
↩️ Torna a Gestione Mescole
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-2">
|
||||
<div class="info-label">ID</div>
|
||||
<div class="info-value" id="hId">-</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="info-label">Nome Interno</div>
|
||||
<div class="info-value" id="hNome">-</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="info-label">Q.tà Totale</div>
|
||||
<div class="info-value" id="hQty">-</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="info-label">Stato</div>
|
||||
<div class="info-value" id="hStato">-</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="info-label">Linee Associate</div>
|
||||
<div class="info-value" id="hLinee">-</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TAB FILE PER CATEGORIA -->
|
||||
<div class="card p-3">
|
||||
<div class="card-body">
|
||||
<ul class="nav nav-tabs" id="fileTabs" role="tablist"></ul>
|
||||
<div class="tab-content pt-3" id="fileTabsContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<!-- MODALE AGGIUNGI FILE -->
|
||||
<div class="modal fade" id="addFileModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header" style="background-color:#cfe3ff;">
|
||||
<h5 class="modal-title">Aggiungi File</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="addFileForm">
|
||||
<input type="hidden" id="fCategoria">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Titolo File</label>
|
||||
<input type="text" class="form-control" id="fTitolo" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">File</label>
|
||||
<input type="file" class="form-control" id="fFile" required>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-add">💾 Carica File</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
|
||||
<script>
|
||||
const idMescola = new URLSearchParams(window.location.search).get('id');
|
||||
let CATEGORIE = {};
|
||||
|
||||
if (!idMescola) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: 'ID mescola mancante'
|
||||
}).then(() => location.href = 'mescole.php');
|
||||
}
|
||||
|
||||
function fmtQty(n) {
|
||||
return Number(n || 0).toLocaleString('it-IT', {
|
||||
minimumFractionDigits: 3,
|
||||
maximumFractionDigits: 3
|
||||
});
|
||||
}
|
||||
|
||||
function loadGeneral() {
|
||||
fetch('get_mescola_general.php?id=' + encodeURIComponent(idMescola))
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
if (!res.success) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: res.message
|
||||
}).then(() => location.href = 'mescole.php');
|
||||
return;
|
||||
}
|
||||
const d = res.data;
|
||||
document.title = 'Scheda Mescola - ' + d.nomeuscita;
|
||||
$('#hNomeUscita').text('🧪 ' + d.nomeuscita);
|
||||
$('#hId').text(d.id);
|
||||
$('#hNome').text(d.nome || '-');
|
||||
$('#hQty').text(fmtQty(d.qty_totale));
|
||||
$('#hStato').html(
|
||||
Number(d.is_active) === 1 ?
|
||||
"<span class='badge bg-success'>Attiva</span>" :
|
||||
"<span class='badge bg-secondary'>Inattiva</span>"
|
||||
);
|
||||
$('#hLinee').text(d.linee || 'Nessuna');
|
||||
});
|
||||
}
|
||||
|
||||
function buildTabs() {
|
||||
fetch('get_mescola_files.php?id=' + encodeURIComponent(idMescola))
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
if (!res.success) return;
|
||||
CATEGORIE = res.categorie;
|
||||
|
||||
const tabsUl = $('#fileTabs');
|
||||
const tabsContent = $('#fileTabsContent');
|
||||
tabsUl.empty();
|
||||
tabsContent.empty();
|
||||
|
||||
let first = true;
|
||||
Object.keys(CATEGORIE).forEach(slug => {
|
||||
const label = CATEGORIE[slug];
|
||||
const activeTab = first ? 'active' : '';
|
||||
const activePane = first ? 'show active' : '';
|
||||
|
||||
tabsUl.append(`
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link ${activeTab}" id="tab-${slug}" data-bs-toggle="tab"
|
||||
data-bs-target="#pane-${slug}" type="button" role="tab">
|
||||
${label}
|
||||
</button>
|
||||
</li>
|
||||
`);
|
||||
|
||||
tabsContent.append(`
|
||||
<div class="tab-pane fade ${activePane}" id="pane-${slug}" role="tabpanel">
|
||||
<div class="d-flex justify-content-end mb-2">
|
||||
<button class="btn btn-add btn-sm add-file-btn" data-categoria="${slug}">
|
||||
➕ Aggiungi File
|
||||
</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped align-middle text-center" id="table-${slug}">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Titolo</th>
|
||||
<th>Nome File</th>
|
||||
<th>Caricato il</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
first = false;
|
||||
});
|
||||
|
||||
// popola ogni tab con i file già caricati
|
||||
Object.keys(CATEGORIE).forEach(slug => loadFilesForCategory(slug));
|
||||
});
|
||||
}
|
||||
|
||||
function loadFilesForCategory(slug) {
|
||||
fetch('get_mescola_files.php?id=' + encodeURIComponent(idMescola) + '&categoria=' + encodeURIComponent(slug))
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
const tbody = $('#table-' + slug + ' tbody');
|
||||
tbody.empty();
|
||||
|
||||
if (!res.success || res.rows.length === 0) {
|
||||
tbody.append(`<tr>
|
||||
<td class="text-muted" colspan="4">Nessun file caricato in questa categoria</td>
|
||||
</tr>`);
|
||||
return;
|
||||
}
|
||||
|
||||
res.rows.forEach(f => {
|
||||
tbody.append(`
|
||||
<tr>
|
||||
<td>${f.titolo}</td>
|
||||
<td><a href="${f.url}" target="_blank" rel="noopener">${f.original_filename}</a></td>
|
||||
<td>${f.uploaded_at}</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-outline-primary" href="${f.url}" target="_blank" rel="noopener">⬇️ Scarica</a>
|
||||
<button class="btn btn-sm btn-outline-danger del-file-btn" data-id="${f.id}" data-categoria="${slug}">🗑️ Elimina</button>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('click', '.add-file-btn', function() {
|
||||
$('#fCategoria').val($(this).data('categoria'));
|
||||
$('#fTitolo').val('');
|
||||
$('#fFile').val('');
|
||||
$('#addFileModal').modal('show');
|
||||
});
|
||||
|
||||
$('#addFileForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const categoria = $('#fCategoria').val();
|
||||
const titolo = $('#fTitolo').val().trim();
|
||||
const fileInput = document.getElementById('fFile');
|
||||
|
||||
if (!fileInput.files.length) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Attenzione',
|
||||
text: 'Seleziona un file'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('idmescola', idMescola);
|
||||
formData.append('categoria', categoria);
|
||||
formData.append('titolo', titolo);
|
||||
formData.append('file', fileInput.files[0]);
|
||||
|
||||
fetch('save_mescola_file.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
if (res.success) {
|
||||
$('#addFileModal').modal('hide');
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'File caricato!'
|
||||
});
|
||||
loadFilesForCategory(categoria);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: res.message || 'Upload non riuscito'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.del-file-btn', function() {
|
||||
const id = $(this).data('id');
|
||||
const categoria = $(this).data('categoria');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Eliminare il file?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Sì, elimina',
|
||||
cancelButtonText: 'Annulla',
|
||||
confirmButtonColor: '#d33'
|
||||
}).then(res => {
|
||||
if (!res.isConfirmed) return;
|
||||
|
||||
fetch('delete_mescola_file.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `id=${encodeURIComponent(id)}`
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
loadFilesForCategory(categoria);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message || 'Cancellazione non riuscita'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
loadGeneral();
|
||||
buildTabs();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user