227 lines
7.8 KiB
JavaScript
227 lines
7.8 KiB
JavaScript
document.addEventListener("DOMContentLoaded", () => {
|
|
// Éléments du DOM
|
|
const invoicesList = document.getElementById("invoicesList");
|
|
const statusFilter = document.getElementById("statusFilter");
|
|
const dateFrom = document.getElementById("dateFrom");
|
|
const dateTo = document.getElementById("dateTo");
|
|
const applyFilters = document.getElementById("applyFilters");
|
|
const modal = document.getElementById("invoiceModal");
|
|
const modalTitle = document.getElementById("modalTitle");
|
|
const modalContent = document.getElementById("modalContent");
|
|
const closeModal = document.getElementById("closeModal");
|
|
|
|
// Charger les factures au démarrage
|
|
loadInvoices();
|
|
|
|
// Gestionnaire d'événements pour les filtres
|
|
applyFilters.addEventListener("click", () => {
|
|
loadInvoices({
|
|
status: statusFilter.value,
|
|
date_from: dateFrom.value,
|
|
date_to: dateTo.value,
|
|
});
|
|
});
|
|
|
|
// Gestionnaire d'événements pour fermer le modal
|
|
closeModal.addEventListener("click", () => {
|
|
modal.classList.add("hidden");
|
|
});
|
|
|
|
// Fonction pour charger les factures
|
|
async function loadInvoices(filters = {}) {
|
|
try {
|
|
const response = await fetch(
|
|
"/api/invoices?" + new URLSearchParams(filters)
|
|
);
|
|
const data = await response.json();
|
|
|
|
// Mettre à jour les statistiques
|
|
updateStatistics(data.statistics);
|
|
|
|
// Mettre à jour la liste des factures
|
|
displayInvoices(data.invoices);
|
|
} catch (error) {
|
|
console.error("Erreur lors du chargement des factures:", error);
|
|
showMessage("Erreur lors du chargement des factures", "error");
|
|
}
|
|
}
|
|
|
|
// Fonction pour mettre à jour les statistiques
|
|
function updateStatistics(stats) {
|
|
document.getElementById("totalInvoices").textContent = stats.total_invoices;
|
|
document.getElementById(
|
|
"totalAmount"
|
|
).textContent = `${stats.total_amount.toFixed(2)} €`;
|
|
document.getElementById(
|
|
"totalPaid"
|
|
).textContent = `${stats.total_paid.toFixed(2)} €`;
|
|
document.getElementById(
|
|
"totalOverdue"
|
|
).textContent = `${stats.total_overdue.toFixed(2)} €`;
|
|
document.getElementById("totalCancelled").textContent = `${(
|
|
stats.total_cancelled || 0
|
|
).toFixed(2)} €`;
|
|
}
|
|
|
|
// Fonction pour afficher les factures
|
|
function displayInvoices(invoices) {
|
|
invoicesList.innerHTML = "";
|
|
|
|
invoices.forEach((invoice) => {
|
|
const row = document.createElement("tr");
|
|
|
|
// Préparer les boutons d'action en fonction du statut
|
|
let actionButtons = `
|
|
<button onclick="viewInvoice(${invoice.id})" class="text-blue-600 hover:text-blue-900 mr-3">
|
|
Voir
|
|
</button>`;
|
|
|
|
// N'afficher le bouton "Marquer comme payée" que si la facture n'est pas déjà payée ou annulée
|
|
if (invoice.status !== "paid" && invoice.status !== "cancelled") {
|
|
actionButtons += `
|
|
<button onclick="updateStatus(${invoice.id}, 'paid')" class="text-green-600 hover:text-green-900 mr-3">
|
|
Marquer comme payée
|
|
</button>`;
|
|
}
|
|
|
|
// N'afficher le bouton "Annuler" que si la facture n'est pas déjà annulée
|
|
if (invoice.status !== "cancelled") {
|
|
actionButtons += `
|
|
<button onclick="updateStatus(${invoice.id}, 'cancelled')" class="text-red-600 hover:text-red-900 mr-3">
|
|
Annuler
|
|
</button>`;
|
|
}
|
|
|
|
// Toujours afficher le bouton de téléchargement
|
|
actionButtons += `
|
|
<button onclick="downloadInvoice(${invoice.id})" class="text-gray-600 hover:text-gray-900">
|
|
Télécharger
|
|
</button>`;
|
|
|
|
row.innerHTML = `
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
|
|
${invoice.invoice_number}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
${invoice.client_name}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
${new Date(invoice.issue_date).toLocaleDateString()}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
${invoice.amount} ${invoice.currency}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
|
|
${getStatusClass(invoice.status)}">
|
|
${getStatusText(invoice.status)}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
${actionButtons}
|
|
</td>
|
|
`;
|
|
invoicesList.appendChild(row);
|
|
});
|
|
}
|
|
|
|
// Fonction pour obtenir la classe CSS du statut
|
|
function getStatusClass(status) {
|
|
switch (status) {
|
|
case "paid":
|
|
return "bg-green-100 text-green-800";
|
|
case "overdue":
|
|
return "bg-red-100 text-red-800";
|
|
case "cancelled":
|
|
return "bg-gray-100 text-gray-800";
|
|
default:
|
|
return "bg-yellow-100 text-yellow-800";
|
|
}
|
|
}
|
|
|
|
// Fonction pour obtenir le texte du statut
|
|
function getStatusText(status) {
|
|
switch (status) {
|
|
case "paid":
|
|
return "Payée";
|
|
case "overdue":
|
|
return "En retard";
|
|
case "cancelled":
|
|
return "Annulée";
|
|
default:
|
|
return "Émise";
|
|
}
|
|
}
|
|
|
|
// Fonction pour afficher une facture
|
|
window.viewInvoice = async (invoiceId) => {
|
|
try {
|
|
const response = await fetch(`/api/invoices/${invoiceId}`);
|
|
const invoice = await response.json();
|
|
|
|
modalTitle.textContent = `Facture ${invoice.invoice_number}`;
|
|
modalContent.innerHTML = `
|
|
<div class="text-left">
|
|
<p><strong>Client:</strong> ${invoice.client_name}</p>
|
|
<p><strong>Date:</strong> ${new Date(
|
|
invoice.issue_date
|
|
).toLocaleDateString()}</p>
|
|
<p><strong>Montant:</strong> ${invoice.amount} ${
|
|
invoice.currency
|
|
}</p>
|
|
<p><strong>Statut:</strong> ${getStatusText(
|
|
invoice.status
|
|
)}</p>
|
|
<p><strong>Adresse:</strong> ${invoice.address}</p>
|
|
<p>${invoice.postal_code} ${invoice.town}</p>
|
|
<p>${invoice.country}</p>
|
|
</div>
|
|
`;
|
|
|
|
modal.classList.remove("hidden");
|
|
} catch (error) {
|
|
console.error("Erreur lors du chargement de la facture:", error);
|
|
showMessage("Erreur lors du chargement de la facture", "error");
|
|
}
|
|
};
|
|
|
|
// Fonction pour mettre à jour le statut d'une facture
|
|
window.updateStatus = async (invoiceId, status) => {
|
|
try {
|
|
await fetch(`/api/invoices/${invoiceId}/status`, {
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ status: status }),
|
|
});
|
|
|
|
loadInvoices();
|
|
showMessage("Statut de la facture mis à jour");
|
|
} catch (error) {
|
|
console.error("Erreur lors de la mise à jour du statut:", error);
|
|
showMessage("Erreur lors de la mise à jour du statut", "error");
|
|
}
|
|
};
|
|
|
|
// Fonction pour télécharger une facture
|
|
window.downloadInvoice = async (invoiceId) => {
|
|
try {
|
|
const response = await fetch(`/api/invoices/${invoiceId}/download`);
|
|
const blob = await response.blob();
|
|
|
|
const url = window.URL.createObjectURL(blob);
|
|
const a = document.createElement("a");
|
|
a.href = url;
|
|
a.download = `invoice_${invoiceId}.pdf`;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
window.URL.revokeObjectURL(url);
|
|
document.body.removeChild(a);
|
|
} catch (error) {
|
|
console.error("Erreur lors du téléchargement de la facture:", error);
|
|
showMessage("Erreur lors du téléchargement de la facture", "error");
|
|
}
|
|
};
|
|
});
|