Initial commit

This commit is contained in:
2024-12-14 13:39:59 +01:00
commit 81f7baf9de
669 changed files with 69828 additions and 0 deletions

53
public/index.html Normal file
View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Calculateur de Prix</title>
</head>
<body>
<!-- Section fixe en haut -->
<div class="header">
<div id="datetime"></div>
<div class="header-row">
<p>Montant Précédent: <span id="previous-amount">0.00 €</span></p>
</div>
</div>
<!-- Bouton "+" toujours visible -->
<div id="add-row-container">
<button id="add-row" class="add-row-button">+</button>
</div>
<!-- Section centrale défilante -->
<div class="articles">
<div id="articles-scroll">
<table id="articles-table">
<thead>
<tr>
<th>Montant (€)</th>
<th>Qtité</th>
<th>Total</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<!-- Section fixe en bas -->
<div class="footer">
<div class="footer-content">
<div class="totals">
<p>Total Articles: <span id="article-total">0.00 €</span></p>
<p>Total Final: <span id="final-total">0.00 €</span></p>
</div>
<button id="save">Enregistrer</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>

131
public/script.js Normal file
View File

@@ -0,0 +1,131 @@
document.addEventListener("DOMContentLoaded", () => {
const datetimeElement = document.getElementById("datetime");
const previousAmountElement = document.getElementById("previous-amount");
const articleTotalElement = document.getElementById("article-total");
const finalTotalElement = document.getElementById("final-total");
const articlesTableBody = document.querySelector("#articles-table tbody");
const addRowButton = document.getElementById("add-row");
const saveButton = document.getElementById("save");
// Mettre à jour la date et l'heure
const updateDatetime = () => {
const now = new Date();
datetimeElement.textContent = now.toLocaleString("fr-FR");
};
setInterval(updateDatetime, 1000);
// Charger le montant précédent
fetch("/montant_precedent")
.then(response => response.text())
.then(data => {
const previousAmount = parseFloat(data) || 0;
previousAmountElement.textContent = `${previousAmount.toFixed(2)}`;
updateTotals();
});
// Ajouter une ligne
addRowButton.addEventListener("click", () => {
const row = document.createElement("tr");
// Montant
const montantCell = document.createElement("td");
const montantInput = document.createElement("input");
montantInput.type = "number";
montantInput.step = "0.01";
montantInput.placeholder = "0.00";
montantCell.appendChild(montantInput);
// Quantité
const quantiteCell = document.createElement("td");
const quantiteSelect = document.createElement("select");
for (let i = 1; i <= 10; i++) {
const option = document.createElement("option");
option.value = i;
option.textContent = i;
quantiteSelect.appendChild(option);
}
quantiteCell.appendChild(quantiteSelect);
// Total
const totalCell = document.createElement("td");
totalCell.textContent = "0.00 €";
// Bouton Option
const optionCell = document.createElement("td");
const optionButton = document.createElement("button");
optionButton.textContent = "Option";
optionButton.addEventListener("click", () => {
const montant = parseFloat(montantInput.value || "0");
montantInput.value = montant > 0 ? -montant : Math.abs(montant);
updateRowTotal();
});
optionCell.appendChild(optionButton);
// Calculer le total de la ligne
const updateRowTotal = () => {
const montant = parseFloat(montantInput.value || "0");
const quantite = parseFloat(quantiteSelect.value || "1");
const total = montant * quantite;
totalCell.textContent = `${total.toFixed(2)}`;
updateTotals();
};
montantInput.addEventListener("input", updateRowTotal);
quantiteSelect.addEventListener("change", updateRowTotal);
// Ajouter les cellules à la ligne
row.appendChild(montantCell);
row.appendChild(quantiteCell);
row.appendChild(totalCell);
row.appendChild(optionCell);
articlesTableBody.appendChild(row);
// Placer le curseur sur le champ montant
montantInput.focus();
});
// Mettre à jour les totaux
const updateTotals = () => {
let articleTotal = 0;
articlesTableBody.querySelectorAll("tr").forEach(row => {
const totalCell = row.cells[2];
articleTotal += parseFloat(totalCell.textContent || "0");
});
articleTotalElement.textContent = `${articleTotal.toFixed(2)}`;
const previousAmount = parseFloat(previousAmountElement.textContent) || 0;
finalTotalElement.textContent = `${(previousAmount + articleTotal).toFixed(2)}`;
};
// Sauvegarder les données
saveButton.addEventListener("click", () => {
const articles = [];
articlesTableBody.querySelectorAll("tr").forEach(row => {
const montant = parseFloat(row.cells[0].querySelector("input").value || "0");
const quantite = parseFloat(row.cells[1].querySelector("select").value || "1");
const total = montant * quantite;
articles.push({ montant, quantite, total });
});
const data = {
date: new Date().toISOString(),
previousAmount: parseFloat(previousAmountElement.textContent) || 0,
articles,
articleTotal: parseFloat(articleTotalElement.textContent) || 0,
finalTotal: parseFloat(finalTotalElement.textContent) || 0
};
fetch("/save", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
}).then(response => {
if (response.ok) {
alert("Données sauvegardées !");
location.reload();
} else {
alert("Erreur lors de la sauvegarde.");
}
});
});
});

150
public/style.css Normal file
View File

@@ -0,0 +1,150 @@
/* Général */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
color: #333;
height: 100vh;
display: flex;
flex-direction: column;
overflow-x: hidden;
}
/* En-tête fixe */
.header {
position: fixed;
top: 0;
width: 100%;
height: 60px;
background-color: #555;
color: white;
padding: 10px 15px;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.header-row {
display: flex;
justify-content: space-between;
align-items: center;
}
#datetime {
font-size: 16px;
font-weight: bold;
}
/* Bouton "+" */
.add-row-button {
position: fixed;
top: 70px;
right: 15px;
z-index: 2000;
padding: 10px 22px;
background-color: #007bff; /* Bleu */
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 20px;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3);
}
.add-row-button:hover {
background-color: #0056b3;
}
/* Section centrale défilante */
.articles {
position: relative;
top: 120px;
bottom: 60px;
padding: 10px;
overflow-y: auto;
background-color: #e9ecef;
flex: 1;
}
#articles-scroll {
overflow-x: auto;
width: 100%;
}
#articles-table {
width: calc(100% - 20px);
max-width: 600px;
border-collapse: collapse;
margin: auto;
}
#articles-table th, #articles-table td {
border: 1px solid #ddd;
padding: 12px;
text-align: center;
font-size: 16px;
}
#articles-table th {
width: 25%;
}
#articles-table td input {
padding: 5px;
width: 90%;
font-size: 16px;
}
#articles-table td button {
background-color: #ffc107;
border: none;
border-radius: 5px;
color: white;
cursor: pointer;
padding: 5px 10px;
font-size: 14px;
}
#articles-table tbody tr:nth-child(even) {
background-color: #f9f9f9;
}
/* Pied de page fixe */
.footer {
position: fixed;
bottom: 0;
width: 100%;
height: 60px;
background-color: #555;
color: white;
padding: 15px 20px;
box-shadow: 0px -2px 5px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.totals p {
margin: 0;
font-size: 18px;
padding-left: 15px;
}
#save {
margin-right: 20px;
padding: 12px 25px;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 18px;
}
#save:hover {
background-color: #218838;
}