← Torna alla Home Dati su disco in locale

Dati salvati su disco esterno



Una tabella su pagina web, il database in file tutti in una cartella su disco esterno in locale "G:". Deve costruire e poter esportare in CVS e PDF, Mail report con diagrammi. La caratteristica è, come abbiamo già fatto, tutto funziona su disco esterno "G:" in locale. I campi: DATA, NOMINATIVO, CODFISC/P.IVA, OPERAZIONE ( CON CONVALIDA DATI "Entrate, Uscite, Garanzia," , EURO, TELEFONO, EMAIL. Ogni riga risponde al comando tramite una spunta. Ogni riga inserita nuova inserisce automaticamente la data odierna. I campi e pulsanti in una maschera separata dai dati, ovvero si vede solo i dati in lavorazione, i dati sono in basso o in altra pagina. Utilizzo senza Internet


1. Preparazione dell'Ambiente (Disco G:)

Nella tua cartella su G:, dovrai avere questa struttura se vuoi che funzioni offline (senza internet):
• gestionale.html (Il codice qui sotto)
• Cartella libs (Opzionale: se non hai internet mentre insegni, dovrai scaricare i file .js di Chart.js e jsPDF e metterli qui, altrimenti il codice sotto usa i link CDN che richiedono internet).

2. Il Codice Completo


<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gestionale Didattico Locale</title>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.25/jspdf.plugin.autotable.min.js"></script>

<style>
/* STILE CSS: Layout e Aspetto */
body { font-family: 'Segoe UI', sans-serif; margin: 0; padding: 0; background-color: #f4f4f4; }

/* Layout a due zone: Maschera Input (Top) e Dati (Bottom) */
.container { max-width: 1200px; margin: 0 auto; padding: 20px; }

/* Sezione Maschera Inserimento */
.input-mask {
background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);
margin-bottom: 20px; border-left: 5px solid #2ecc71;
}

.input-mask h2 { margin-top: 0; color: #333; }

.form-grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;
}

.form-group label { display: block; margin-bottom: 5px; font-weight: bold; font-size: 0.9em; }
.form-group input, .form-group select {
width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box;
}

/* Pulsanti */
.btn-group { margin-top: 20px; display: flex; gap: 10px; flex-wrap: wrap; }
button {
padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; color: white; font-weight: bold;
}
.btn-add { background-color: #2ecc71; } /* Verde */
.btn-csv { background-color: #3498db; } /* Blu */
.btn-pdf { background-color: #e74c3c; } /* Rosso */
.btn-mail { background-color: #f1c40f; color: #333; } /* Giallo */
.btn-save { background-color: #9b59b6; } /* Viola - DB */

/* Sezione Tabella Dati */
.data-view {
background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

table { width: 100%; border-collapse: collapse; margin-top: 10px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #f8f9fa; color: #333; }
tr:hover { background-color: #f1f1f1; }

/* Colore per le operazioni */
.op-entrata { color: green; font-weight: bold; }
.op-uscita { color: red; font-weight: bold; }
.op-garanzia { color: orange; font-weight: bold; }

/* Area Grafico (nascosta di default) */
#chartContainer { margin-top: 20px; display: none; height: 300px; }
</style>
</head>
<body>

<div class="container">

<div class="input-mask">
<h2>Gestione Operazioni</h2>
<div class="form-grid">
<div class="form-group">
<label>Data (Automatica)</label>
<input type="date" id="inputData" readonly>
</div>
<div class="form-group">
<label>Nominativo</label>
<input type="text" id="inputNome" placeholder="Mario Rossi">
</div>
<div class="form-group">
<label>Cod. Fisc / P.IVA</label>
<input type="text" id="inputCF" placeholder="CODICE...">
</div>
<div class="form-group">
<label>Operazione</label>
<select id="inputOp">
<option value="Entrate">Entrate</option>
<option value="Uscite">Uscite</option>
<option value="Garanzia">Garanzia</option>
</select>
</div>
<div class="form-group">
<label>Euro (€)</label>
<input type="number" id="inputEuro" step="0.01" placeholder="0.00">
</div>
<div class="form-group">
<label>Telefono</label>
<input type="tel" id="inputTel" placeholder="333...">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" id="inputEmail" placeholder="email@esempio.com">
</div>
</div>

<div class="btn-group">
<button class="btn-add" onclick="aggiungiRiga()">+ Aggiungi Riga</button>
<button class="btn-save" onclick="salvaDatabase()">💾 Salva DB su Disco</button>
<button class="btn-save" onclick="document.getElementById('fileInput').click()">📂 Carica DB</button>
<input type="file" id="fileInput" style="display: none;" onchange="caricaDatabase(this)">
</div>

<hr>

<div class="btn-group">
<button class="btn-csv" onclick="esportaCSV()">Esporta CSV</button>
<button class="btn-pdf" onclick="esportaPDF()">Esporta PDF</button>
<button class="btn-mail" onclick="generaReportMail()">📧 Report Mail & Grafici</button>
</div>

<div id="chartContainer">
<canvas id="myChart"></canvas>
</div>
</div>

<div class="data-view">
<h3>Database Dati</h3>
<table id="mainTable">
<thead>
<tr>
<th>Sel.</th>
<th>Data</th>
<th>Nominativo</th>
<th>CF/P.IVA</th>
<th>Operazione</th>
<th>Euro</th>
<th>Telefono</th>
<th>Email</th>
<th>Azioni</th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
</div>

</div>

<script>
/**
* LOGICA JAVASCRIPT
* Scopo: Gestione array di oggetti, manipolazione DOM, Export file.
*/

// 1. STATO DELL'APPLICAZIONE (Il nostro Database in memoria RAM)
let database = [];

// Al caricamento della pagina
window.onload = function() {
// Imposta la data odierna nel campo input
document.getElementById('inputData').valueAsDate = new Date();

// Controlla se c'è un salvataggio precedente nel LocalStorage (memoria browser)
const savedData = localStorage.getItem('db_gestionale_g');
if (savedData) {
database = JSON.parse(savedData);
renderTable();
}
};

// 2. FUNZIONE: Aggiungi Riga
function aggiungiRiga() {
// Recupero valori dal DOM
const data = document.getElementById('inputData').value;
const nome = document.getElementById('inputNome').value;
const cf = document.getElementById('inputCF').value;
const op = document.getElementById('inputOp').value;
const euro = parseFloat(document.getElementById('inputEuro').value) || 0;
const tel = document.getElementById('inputTel').value;
const email = document.getElementById('inputEmail').value;

// Validazione minima

if(nome === "" || euro === 0) {
alert("Compilare almeno Nome e Importo!");
return;
}

// Creazione Oggetto Riga

const nuovaRiga = {
id: Date.now(), // timestamp univoco
selezionato: false,
data: data,
nominativo: nome,
codfisc: cf,
operazione: op,
euro: euro,
telefono: tel,
email: email
};

// Aggiorna Array e Vista
database.push(nuovaRiga);
salvaInLocale(); // Salva nel browser
renderTable(); // Ridisegna tabella

// Reset campi (tranne la data che resta odierna)
document.getElementById('inputNome').value = "";
document.getElementById('inputEuro').value = "";
}

// 3. FUNZIONE: Disegna Tabella (Render)
function renderTable() {
const tbody = document.getElementById('tableBody');
tbody.innerHTML = ""; // Pulisce tabella attuale

database.forEach((riga, index) => {
// Determina classe CSS per colore operazione
let colorClass = "";
if(riga.operazione === "Entrate") colorClass = "op-entrata";
else if(riga.operazione === "Uscite") colorClass = "op-uscita";
else colorClass = "op-garanzia";

const tr = document.createElement('tr');
tr.innerHTML = `
<td><input type="checkbox" onchange="toggleSelezione(${index})" ${riga.selezionato ? 'checked' : ''}></td>
<td>${riga.data}</td>
<td>${riga.nominativo}</td>
<td>${riga.codfisc}</td>
<td class="${colorClass}">${riga.operazione}</td>
<td>€ ${riga.euro.toFixed(2)}</td>
<td>${riga.telefono}</td>
<td>${riga.email}</td>
<td><button onclick="rimuoviRiga(${index})" style="background:#e74c3c; padding:5px;">X</button></td>
`;
tbody.appendChild(tr);
});
}

// Gestione Spunta/Selezione
function toggleSelezione(index) {
database[index].selezionato = !database[index].selezionato;
salvaInLocale();
}

// Rimuovi riga
function rimuoviRiga(index) {
if(confirm("Eliminare questa riga?")) {
database.splice(index, 1);
salvaInLocale();
renderTable();
}
}

// 4. PERSISTENZA DATI (Simulazione DB su File)

// Salva nel browser (veloce)
function salvaInLocale() {
localStorage.setItem('db_gestionale_g', JSON.stringify(database));
}

// Salva su Disco G: (Download file JSON)
function salvaDatabase() {
const dataStr = JSON.stringify(database, null, 2);
const blob = new Blob([dataStr], { type: "application/json" });
const url = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = url;
a.download = "database_gestionale.json"; // Nome file su disco
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}

// Carica da Disco G:
function caricaDatabase(input) {
const file = input.files[0];
if (!file) return;

const reader = new FileReader();
reader.onload = function(e) {
try {
database = JSON.parse(e.target.result);
salvaInLocale();
renderTable();
alert("Database caricato con successo!");
} catch(err) {
alert("Errore nel file database.");
}
};
reader.readAsText(file);
}

// 5. ESPORTAZIONE CSV
function esportaCSV() {
let csvContent = "data:text/csv;charset=utf-8,";
csvContent += "Data,Nominativo,CF,Operazione,Euro,Telefono,Email\n"; // Intestazione

database.forEach(row => {
// Solo se selezionato? Se nessuno selezionato, esporta tutto.
// Qui esportiamo tutto per semplicità, oppure filtriamo:
// const rowsToExport = database.filter(r => r.selezionato).length > 0 ? database.filter(r => r.selezionato) : database;

let rowStr = `${row.data},${row.nominativo},${row.codfisc},${row.operazione},${row.euro},${row.telefono},${row.email}`;
csvContent += rowStr + "\n";
});

const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "export_dati.csv");
document.body.appendChild(link);
link.click();
}

// 6. ESPORTAZIONE PDF (Libreria jsPDF)
function esportaPDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();

doc.text("Report Gestionale", 14, 15);

// Colonne e righe per autoTable
const tableColumn = ["Data", "Nominativo", "Operazione", "Euro"];
const tableRows = [];

database.forEach(row => {
const rowData = [row.data, row.nominativo, row.operazione, row.euro.toFixed(2)];
tableRows.push(rowData);
});

doc.autoTable({
head: [tableColumn],
body: tableRows,
startY: 20,
});

doc.save("report_gestionale.pdf");
}

// 7. GRAFICI E MAIL (Reportistica)
function generaReportMail() {
// A. Calcolo Totali per il grafico
let totEntrate = 0;
let totUscite = 0;
let totGaranzia = 0;

database.forEach(r => {
if(r.operazione === "Entrate") totEntrate += r.euro;
if(r.operazione === "Uscite") totUscite += r.euro;
if(r.operazione === "Garanzia") totGaranzia += r.euro;
});

// B. Generazione Grafico a Torta (Chart.js)
document.getElementById('chartContainer').style.display = 'block';
const ctx = document.getElementById('myChart').getContext('2d');

// Distruggiamo il grafico precedente se esiste per rifarlo
if(window.myPieChart) window.myPieChart.destroy();

window.myPieChart = new Chart(ctx, {
type: 'pie', // O 'bar'
data: {
labels: ['Entrate', 'Uscite', 'Garanzia'],
datasets: [{
data: [totEntrate, totUscite, totGaranzia],
backgroundColor: ['#2ecc71', '#e74c3c', '#f1c40f']
}]
},
options: { responsive: true, maintainAspectRatio: false }
});

// C. Creazione Mailto (Simulazione invio mail)
// Nota didattica: Non si può allegare l'immagine del grafico direttamente via mailto standard HTML.
// Si inviano i dati testuali.

const subject = "Report Gestionale Giornaliero";
const body = `Buongiorno,%0D%0A%0D%0AEcco il riepilogo operazioni:%0D%0A` +
`- Totale Entrate: € ${totEntrate.toFixed(2)}%0D%0A` +
`- Totale Uscite: € ${totUscite.toFixed(2)}%0D%0A` +
`- Totale Garanzia: € ${totGaranzia.toFixed(2)}%0D%0A%0D%0A` +
`Il grafico è visibile sulla dashboard locale.`;

window.location.href = `mailto:?subject=${subject}&body=${body}`;
}

</script>

</body>
</html>