document.addEventListener("DOMContentLoaded", () => { const form = document.getElementById("invoiceForm"); const invoiceItems = document.getElementById("invoiceItems"); const addItemButton = document.getElementById("addItemButton"); const clearFormButton = document.createElement("button"); const recipientNameInput = form.recipient_name; const clientSuggestions = document.createElement("div"); // Configuration de la boîte de suggestions clientSuggestions.className = "client-suggestions absolute z-10 bg-white shadow-lg rounded-md w-full max-h-60 overflow-y-auto hidden"; recipientNameInput.parentNode.style.position = "relative"; recipientNameInput.parentNode.appendChild(clientSuggestions); // Charger les clients précédents let clientsData = JSON.parse(localStorage.getItem("clientsData") || "[]"); // Ajouter un bouton pour effacer le formulaire clearFormButton.type = "button"; clearFormButton.className = "bg-red-500 text-white px-4 py-2 rounded-md hover:bg-red-600 ml-4"; clearFormButton.textContent = "Effacer le formulaire"; clearFormButton.id = "clearFormButton"; // Ajouter le bouton après le bouton de soumission const submitButton = form.querySelector('button[type="submit"]'); submitButton.parentNode.insertBefore( clearFormButton, submitButton.nextSibling ); // Gestionnaire d'événement pour effacer le formulaire clearFormButton.addEventListener("click", () => { if (confirm("Êtes-vous sûr de vouloir effacer le formulaire ?")) { localStorage.removeItem("invoiceData"); form.reset(); // Réinitialiser les lignes de facturation invoiceItems.innerHTML = ""; addInvoiceItem(); showMessage("Formulaire effacé", "success"); } }); // Restaurer les données du formulaire depuis localStorage si elles existent restoreFormData(); // Initialiser avec une ligne de facturation par défaut ou restaurer les lignes sauvegardées if (invoiceItems.children.length === 0) { addInvoiceItem(); } // Ajouter une ligne de facturation lorsqu'on clique sur le bouton addItemButton.addEventListener("click", addInvoiceItem); // Sauvegarder les données pendant la saisie (debounced) let saveTimeout; form.addEventListener("input", () => { clearTimeout(saveTimeout); saveTimeout = setTimeout(() => { saveFormData(); }, 500); // Attendre 500ms après la dernière saisie }); // Gérer l'auto-complétion des clients recipientNameInput.addEventListener("input", function () { const query = this.value.toLowerCase(); if (query.length < 2) { clientSuggestions.classList.add("hidden"); return; } // Filtrer les clients qui correspondent à la recherche const matches = clientsData.filter((client) => client.name.toLowerCase().includes(query) ); if (matches.length === 0) { clientSuggestions.classList.add("hidden"); return; } // Afficher les suggestions clientSuggestions.innerHTML = matches .map( (client) => `
${client.name}
${client.address}, ${client.postal_code} ${client.town}
` ) .join(""); clientSuggestions.classList.remove("hidden"); // Ajouter des gestionnaires d'événements pour les suggestions document.querySelectorAll(".client-suggestion").forEach((suggestion) => { suggestion.addEventListener("click", function () { const clientId = this.getAttribute("data-client-id"); const client = clientsData.find((c) => c.id === clientId); if (client) { fillClientData(client); clientSuggestions.classList.add("hidden"); } }); }); }); // Masquer les suggestions lorsqu'on clique ailleurs document.addEventListener("click", function (e) { if ( !recipientNameInput.contains(e.target) && !clientSuggestions.contains(e.target) ) { clientSuggestions.classList.add("hidden"); } }); // Fonction pour remplir les données du client function fillClientData(client) { form.recipient_name.value = client.name; form.recipient_address.value = client.address; form.recipient_postal_code.value = client.postal_code; form.recipient_town.value = client.town; form.recipient_country.value = client.country; if (client.vat_number) { form.recipient_vat_number.value = client.vat_number; } } // Fonction pour sauvegarder un nouveau client function saveClient() { // Ne sauvegarder que si les champs essentiels sont remplis if ( !form.recipient_name.value || !form.recipient_address.value || !form.recipient_postal_code.value || !form.recipient_town.value ) { return; } const clientData = { id: Date.now().toString(), // ID unique name: form.recipient_name.value, address: form.recipient_address.value, postal_code: form.recipient_postal_code.value, town: form.recipient_town.value, country: form.recipient_country.value, vat_number: form.recipient_vat_number.value || null, lastUsed: new Date().toISOString(), }; // Vérifier si le client existe déjà (par nom) const existingClientIndex = clientsData.findIndex( (client) => client.name.toLowerCase() === clientData.name.toLowerCase() ); if (existingClientIndex !== -1) { // Mettre à jour le client existant clientsData[existingClientIndex] = { ...clientsData[existingClientIndex], ...clientData, id: clientsData[existingClientIndex].id, // Conserver l'ID d'origine }; } else { // Ajouter le nouveau client clientsData.push(clientData); } // Trier par date d'utilisation (plus récent en premier) clientsData.sort((a, b) => new Date(b.lastUsed) - new Date(a.lastUsed)); // Limiter à 50 clients clientsData = clientsData.slice(0, 50); // Sauvegarder dans localStorage localStorage.setItem("clientsData", JSON.stringify(clientsData)); } // Fonction pour sauvegarder les données du formulaire function saveFormData() { const formData = { language: form.language.value, invoice_number: form.invoice_number.value, amount: form.amount.value, currency: form.currency.value, recipient_name: form.recipient_name.value, recipient_address: form.recipient_address.value, recipient_postal_code: form.recipient_postal_code.value, recipient_town: form.recipient_town.value, recipient_country: form.recipient_country.value, recipient_vat_number: form.recipient_vat_number.value || null, items: collectInvoiceItems(), }; localStorage.setItem("invoiceData", JSON.stringify(formData)); // Sauvegarder aussi dans l'historique des factures récentes saveToRecentInvoices(formData); // Sauvegarder les informations du client si tous les champs sont remplis saveClient(); } // Fonction pour sauvegarder dans l'historique des factures récentes function saveToRecentInvoices(formData) { if (!formData.recipient_name) return; // Ne pas sauvegarder si pas de nom de destinataire let recentInvoices = JSON.parse( localStorage.getItem("recentInvoices") || "[]" ); // Créer un identifiant unique basé sur le nom et la date const now = new Date(); const id = `${formData.recipient_name}_${now.toISOString()}`; // Ajouter la facture actuelle à l'historique avec un timestamp const invoiceWithMeta = { ...formData, id, lastEdited: now.toISOString(), }; // Vérifier si une facture similaire existe déjà (même destinataire) const existingIndex = recentInvoices.findIndex( (invoice) => invoice.recipient_name === formData.recipient_name ); if (existingIndex !== -1) { // Remplacer la facture existante recentInvoices[existingIndex] = invoiceWithMeta; } else { // Ajouter la nouvelle facture recentInvoices.unshift(invoiceWithMeta); } // Limiter à 10 factures récentes recentInvoices = recentInvoices.slice(0, 10); localStorage.setItem("recentInvoices", JSON.stringify(recentInvoices)); // Mettre à jour la liste des factures récentes dans l'interface updateRecentInvoicesList(); } // Fonction pour mettre à jour la liste des factures récentes dans l'interface function updateRecentInvoicesList() { const recentInvoicesContainer = document.getElementById("recentInvoices"); if (!recentInvoicesContainer) { // Créer le conteneur s'il n'existe pas const container = document.createElement("div"); container.id = "recentInvoices"; container.className = "mt-8 bg-white rounded-lg shadow p-4"; container.innerHTML = `

Factures récentes

`; form.parentNode.insertBefore(container, form.nextSibling); } const recentInvoicesList = document.getElementById("recentInvoicesList"); const recentInvoices = JSON.parse( localStorage.getItem("recentInvoices") || "[]" ); if (recentInvoices.length === 0) { recentInvoicesList.innerHTML = `

Aucune facture récente

`; return; } recentInvoicesList.innerHTML = recentInvoices .map( (invoice) => `
${invoice.recipient_name} ${invoice.amount} ${ invoice.currency } ${new Date( invoice.lastEdited ).toLocaleDateString()}
` ) .join(""); // Ajouter les gestionnaires d'événements pour charger les factures document.querySelectorAll(".load-invoice").forEach((button) => { button.addEventListener("click", (e) => { const id = e.target.getAttribute("data-id"); const invoice = recentInvoices.find((inv) => inv.id === id); if (invoice) { if ( confirm( "Charger cette facture ? Les données actuelles seront remplacées." ) ) { loadInvoice(invoice); } } }); }); } // Fonction pour charger une facture depuis l'historique function loadInvoice(invoice) { // Remplir le formulaire avec les données de la facture form.language.value = invoice.language || ""; form.invoice_number.value = invoice.invoice_number || ""; form.amount.value = invoice.amount || ""; form.currency.value = invoice.currency || "EUR"; form.recipient_name.value = invoice.recipient_name || ""; form.recipient_address.value = invoice.recipient_address || ""; form.recipient_postal_code.value = invoice.recipient_postal_code || ""; form.recipient_town.value = invoice.recipient_town || ""; form.recipient_country.value = invoice.recipient_country || ""; form.recipient_vat_number.value = invoice.recipient_vat_number || ""; // Restaurer les lignes de facturation invoiceItems.innerHTML = ""; if (invoice.items && invoice.items.length > 0) { invoice.items.forEach((item) => { addInvoiceItem(item.description, item.amount); }); } else { addInvoiceItem(); } // Sauvegarder dans le localStorage localStorage.setItem("invoiceData", JSON.stringify(invoice)); showMessage("Facture chargée avec succès", "success"); } // Fonction pour restaurer les données du formulaire depuis localStorage function restoreFormData() { const savedData = localStorage.getItem("invoiceData"); if (!savedData) { // Mettre à jour la liste des factures récentes même s'il n'y a pas de données sauvegardées updateRecentInvoicesList(); return; } try { const formData = JSON.parse(savedData); // Remplir les champs du formulaire if (formData.language) form.language.value = formData.language; if (formData.invoice_number) form.invoice_number.value = formData.invoice_number; if (formData.amount) form.amount.value = formData.amount; if (formData.currency) form.currency.value = formData.currency; if (formData.recipient_name) form.recipient_name.value = formData.recipient_name; if (formData.recipient_address) form.recipient_address.value = formData.recipient_address; if (formData.recipient_postal_code) form.recipient_postal_code.value = formData.recipient_postal_code; if (formData.recipient_town) form.recipient_town.value = formData.recipient_town; if (formData.recipient_country) form.recipient_country.value = formData.recipient_country; if (formData.recipient_vat_number) form.recipient_vat_number.value = formData.recipient_vat_number; // Restaurer les lignes de facturation if (formData.items && formData.items.length > 0) { // Vider les lignes existantes invoiceItems.innerHTML = ""; // Ajouter chaque ligne sauvegardée formData.items.forEach((item) => { addInvoiceItem(item.description, item.amount); }); } // Mettre à jour la liste des factures récentes updateRecentInvoicesList(); } catch (error) { console.error("Erreur lors de la restauration des données:", error); } } // Fonction pour créer une nouvelle ligne de facturation function addInvoiceItem(description = "", amount = "") { const itemId = Date.now(); // ID unique pour l'élément const itemDiv = document.createElement("div"); itemDiv.className = "invoice-item grid grid-cols-5 gap-2"; itemDiv.dataset.id = itemId; itemDiv.innerHTML = `
`; // Ajouter un gestionnaire d'événements pour supprimer la ligne const deleteButton = itemDiv.querySelector(".delete-item"); deleteButton.addEventListener("click", function () { const id = this.getAttribute("data-id"); deleteInvoiceItem(id); }); invoiceItems.appendChild(itemDiv); } // Fonction pour supprimer une ligne de facturation function deleteInvoiceItem(id) { const item = document.querySelector(`.invoice-item[data-id="${id}"]`); if (item) { item.remove(); } // S'assurer qu'il reste au moins une ligne if (invoiceItems.children.length === 0) { addInvoiceItem(); } } // Fonction pour collecter toutes les lignes de facturation function collectInvoiceItems() { const items = []; document.querySelectorAll(".invoice-item").forEach((item) => { const id = item.dataset.id; const description = item.querySelector( `[name="item_description_${id}"]` ).value; const amount = item.querySelector(`[name="item_amount_${id}"]`).value; if (description && amount) { items.push({ description, amount }); } }); return items; } // Fonction pour valider le formulaire function validateForm() { const requiredFields = [ form.invoice_number, form.amount, form.recipient_name, form.recipient_address, form.recipient_postal_code, form.recipient_town, form.recipient_country, ]; for (const field of requiredFields) { if (!field.value) { showMessage(`Le champ ${field.name} est requis`, "error"); field.focus(); return false; } } const items = collectInvoiceItems(); if (items.length === 0) { showMessage("Ajoutez au moins une ligne de facturation", "error"); return false; } return true; } // Fonction pour afficher les messages function showMessage(message, type = "success") { const messageDiv = document.createElement("div"); messageDiv.className = `${type}-message fixed top-4 right-4 p-4 rounded-md shadow-lg ${ type === "success" ? "bg-green-500" : "bg-red-500" } text-white`; messageDiv.textContent = message; document.body.appendChild(messageDiv); // Afficher le message setTimeout(() => messageDiv.classList.add("opacity-100"), 100); // Supprimer le message après 3 secondes setTimeout(() => { messageDiv.classList.remove("opacity-100"); setTimeout(() => messageDiv.remove(), 300); }, 3000); } // Gestionnaire de soumission du formulaire form.addEventListener("submit", function (e) { e.preventDefault(); if (!validateForm()) { return; } // Récupérer les données du formulaire const formData = { language: form.language.value, invoice_number: form.invoice_number.value, amount: form.amount.value, // Montant total currency: form.currency.value, recipient_name: form.recipient_name.value, recipient_address: form.recipient_address.value, recipient_postal_code: form.recipient_postal_code.value, recipient_town: form.recipient_town.value, recipient_country: form.recipient_country.value, recipient_vat_number: form.recipient_vat_number.value || null, items: collectInvoiceItems(), // Ajouter les lignes de facturation }; // Sauvegarder les données du formulaire dans localStorage localStorage.setItem("invoiceData", JSON.stringify(formData)); // Sauvegarder les informations du client saveClient(); // Rediriger vers la page de prévisualisation avec les données const queryString = encodeURIComponent(JSON.stringify(formData)); window.location.href = `/preview?data=${queryString}`; }); });