`;
}
}
// Fonction pour changer d'onglet
function switchTab(tabId) {
// Mettre à jour les classes des boutons
tabButtons.forEach((button) => {
const buttonTabId = button.id.replace("tab", "").toLowerCase();
if (buttonTabId === tabId) {
button.classList.add("active", "border-blue-500", "text-blue-600");
button.classList.remove("border-transparent", "text-gray-500");
} else {
button.classList.remove("active", "border-blue-500", "text-blue-600");
button.classList.add("border-transparent", "text-gray-500");
}
});
// Afficher le contenu de l'onglet sélectionné
tabContents.forEach((content) => {
const contentId = content.id;
if (contentId === `${tabId}Content`) {
content.classList.remove("hidden");
} else {
content.classList.add("hidden");
}
});
}
// Génération de couleurs pour les graphiques
function generateChartColors(count = 10) {
const colors = [
"#4F46E5",
"#10B981",
"#F59E0B",
"#EF4444",
"#EC4899",
"#8B5CF6",
"#06B6D4",
"#84CC16",
"#F97316",
"#6366F1",
];
// Si on a besoin de plus de couleurs, on les génère aléatoirement
if (count > colors.length) {
for (let i = colors.length; i < count; i++) {
const r = Math.floor(Math.random() * 200);
const g = Math.floor(Math.random() * 200);
const b = Math.floor(Math.random() * 200);
colors.push(`rgb(${r}, ${g}, ${b})`);
}
}
return colors;
}
// Mise à jour des graphiques
function updateCharts(statistics) {
updateRevenuesChart(statistics.revenue_by_category);
updateExpensesChart(statistics.expenses_by_category);
}
// Mise à jour du graphique des revenus
function updateRevenuesChart(revenuesByCategory) {
const ctx = document.getElementById("revenuesByCategoryChart");
const colors = generateChartColors(Object.keys(revenuesByCategory).length);
// Détruire le graphique précédent s'il existe
if (revenuesChart) {
revenuesChart.destroy();
}
// Créer le nouveau graphique
revenuesChart = new Chart(ctx, {
type: "pie",
data: {
labels: Object.keys(revenuesByCategory),
datasets: [
{
data: Object.values(revenuesByCategory),
backgroundColor: colors,
borderWidth: 1,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "right",
},
tooltip: {
callbacks: {
label: function (context) {
const value = context.raw;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${value.toFixed(2)} € (${percentage}%)`;
},
},
},
},
},
});
// Mettre à jour la liste des revenus par catégorie
updateCategoryList(revenuesByCategoryList, revenuesByCategory);
}
// Mise à jour du graphique des dépenses
function updateExpensesChart(expensesByCategory) {
const ctx = document.getElementById("expensesByCategoryChart");
const colors = generateChartColors(Object.keys(expensesByCategory).length);
// Détruire le graphique précédent s'il existe
if (expensesChart) {
expensesChart.destroy();
}
// Créer le nouveau graphique
expensesChart = new Chart(ctx, {
type: "pie",
data: {
labels: Object.keys(expensesByCategory),
datasets: [
{
data: Object.values(expensesByCategory),
backgroundColor: colors,
borderWidth: 1,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "right",
},
tooltip: {
callbacks: {
label: function (context) {
const value = context.raw;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${value.toFixed(2)} € (${percentage}%)`;
},
},
},
},
},
});
// Mettre à jour la liste des dépenses par catégorie
updateCategoryList(expensesByCategoryList, expensesByCategory);
}
// Mise à jour des listes de catégories
function updateCategoryList(listElement, categoryData) {
listElement.innerHTML = "";
const total = Object.values(categoryData).reduce((a, b) => a + b, 0);
Object.entries(categoryData)
.sort((a, b) => b[1] - a[1]) // Trier par montant décroissant
.forEach(([category, amount]) => {
const percentage = ((amount / total) * 100).toFixed(1);
const row = document.createElement("tr");
row.innerHTML = `
${category}
${amount.toFixed(2)} €
${percentage}%
`;
listElement.appendChild(row);
});
}
// Fonctions globales pour l'édition et la suppression
window.editTransaction = async (transactionId) => {
alert("Fonctionnalité d'édition à implémenter");
// TODO: Implémenter l'édition des transactions
};
window.deleteTransaction = async (transactionId) => {
if (confirm("Êtes-vous sûr de vouloir supprimer cette transaction ?")) {
try {
const response = await fetch(
`/api/accounting/transaction/${transactionId}`,
{
method: "DELETE",
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
showMessage("Transaction supprimée avec succès");
loadData();
} catch (error) {
console.error("Erreur lors de la suppression:", error);
showMessage("Erreur lors de la suppression", "error");
}
}
};
// Fonction pour afficher des messages à l'utilisateur
function showMessage(message, type = "success") {
// On pourrait implémenter un système de notification plus élaboré ici
alert(message);
}
});