Spaces:
Running
Running
créer un formulaire de saisie un imprimerie dans excel, userform contient 8 champs id du produit, nom du produits,prix du produit,quantite,date et mois,type: entre et sorties, stock, et listView avec entête et quadrillage et avec 5 boutons , ajouter,modifier,rechercher,supprimer,imprimer avec boite de saisie, nom de la feuille base de données, afficher les donnees dans listview en temp reel. et un rapport par semaine , mois et annee et benefice et total de vente. devise en franc guineen pour tout rapport
359a921 verified | <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Rapports - PrintPro Manager</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script> | |
| <style> | |
| .fade-in { | |
| animation: fadeIn 0.5s; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .hover-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .btn-secondary { | |
| background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="mb-10 text-center"> | |
| <h1 class="text-4xl font-bold text-gray-800 mb-2">Rapports 📊</h1> | |
| <p class="text-gray-600">Analyse des ventes et performances</p> | |
| <div class="mt-4 flex justify-center space-x-4"> | |
| <button onclick="window.location.href='index.html'" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> | |
| Accueil | |
| </button> | |
| <button onclick="window.location.href='products.html'" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"> | |
| Gestion des Produits | |
| </button> | |
| <button onclick="window.location.href='reports.html'" class="bg-purple-500 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded"> | |
| Rapports | |
| </button> | |
| </div> | |
| </header> | |
| <!-- Statistiques --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <div class="flex items-center"> | |
| <div class="p-3 rounded-full bg-blue-100 text-blue-600 mr-4"> | |
| <i data-feather="calendar" class="w-6 h-6"></i> | |
| </div> | |
| <div> | |
| <p class="text-sm text-gray-600">Ventes hebdomadaires</p> | |
| <p class="text-2xl font-bold text-blue-600" id="weeklySales">0 GNF</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <div class="flex items-center"> | |
| <div class="p-3 rounded-full bg-green-100 text-green-600 mr-4"> | |
| <i data-feather="calendar" class="w-6 h-6"></i> | |
| </div> | |
| <div> | |
| <p class="text-sm text-gray-600">Ventes mensuelles</p> | |
| <p class="text-2xl font-bold text-green-600" id="monthlySales">0 GNF</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <div class="flex items-center"> | |
| <div class="p-3 rounded-full bg-purple-100 text-purple-600 mr-4"> | |
| <i data-feather="calendar" class="w-6 h-6"></i> | |
| </div> | |
| <div> | |
| <p class="text-sm text-gray-600">Ventes annuelles</p> | |
| <p class="text-2xl font-bold text-purple-600" id="yearlySales">0 GNF</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <div class="flex items-center"> | |
| <div class="p-3 rounded-full bg-yellow-100 text-yellow-600 mr-4"> | |
| <i data-feather="trending-up" class="w-6 h-6"></i> | |
| </div> | |
| <div> | |
| <p class="text-sm text-gray-600">Bénéfice total</p> | |
| <p class="text-2xl font-bold text-yellow-600" id="totalProfit">0 GNF</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Graphiques --> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8"> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <h2 class="text-xl font-bold text-gray-800 mb-4">Ventes par Mois</h2> | |
| <canvas id="monthlyChart" height="300"></canvas> | |
| </div> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <h2 class="text-xl font-bold text-gray-800 mb-4">Types de Transactions</h2> | |
| <canvas id="typeChart" height="300"></canvas> | |
| </div> | |
| </div> | |
| <!-- Liste des produits --> | |
| <div class="bg-white rounded-xl shadow-lg p-6 hover-card transition-all duration-300 fade-in"> | |
| <div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 flex items-center"> | |
| <i data-feather="database" class="mr-2"></i>Liste des Produits | |
| </h2> | |
| <div class="mt-4 md:mt-0 flex space-x-3"> | |
| <div class="relative"> | |
| <input type="text" id="searchInput" placeholder="Rechercher..." class="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent"> | |
| <i data-feather="search" class="absolute left-3 top-2.5 text-gray-400"></i> | |
| </div> | |
| <button id="printBtn" class="btn-secondary text-white px-4 py-2 rounded-lg flex items-center"> | |
| <i data-feather="printer" class="mr-2"></i>Imprimer | |
| </button> | |
| </div> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full divide-y divide-gray-200"> | |
| <thead class="bg-gray-50"> | |
| <tr> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Produit</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Prix</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Quantité</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Mois</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Stock</th> | |
| </tr> | |
| </thead> | |
| <tbody id="productList" class="bg-white divide-y divide-gray-200"> | |
| <!-- Les données seront insérées ici dynamiquement --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Données en mémoire | |
| let products = JSON.parse(localStorage.getItem('products')) || []; | |
| // Initialisation | |
| document.addEventListener('DOMContentLoaded', function() { | |
| feather.replace(); | |
| updateReports(); | |
| renderProductList(); | |
| document.getElementById('searchInput').addEventListener('input', filterProducts); | |
| document.getElementById('printBtn').addEventListener('click', printData); | |
| }); | |
| // Mettre à jour les rapports | |
| function updateReports() { | |
| // Calculer les ventes hebdomadaires (7 derniers jours) | |
| const weeklySales = calculateSalesForPeriod(7); | |
| document.getElementById('weeklySales').textContent = `${Math.round(weeklySales)} GNF`; | |
| // Calculer les ventes mensuelles (30 derniers jours) | |
| const monthlySales = calculateSalesForPeriod(30); | |
| document.getElementById('monthlySales').textContent = `${Math.round(monthlySales)} GNF`; | |
| // Calculer les ventes annuelles (365 derniers jours) | |
| const yearlySales = calculateSalesForPeriod(365); | |
| document.getElementById('yearlySales').textContent = `${Math.round(yearlySales)} GNF`; | |
| // Calculer le bénéfice total | |
| const totalProfit = products.reduce((sum, product) => sum + (Math.round(product.price) * product.quantity), 0); | |
| document.getElementById('totalProfit').textContent = `${Math.round(totalProfit)} GNF`; | |
| // Mettre à jour les graphiques | |
| updateCharts(); | |
| } | |
| // Calculer les ventes pour une période donnée | |
| function calculateSalesForPeriod(days) { | |
| const now = new Date(); | |
| const startDate = new Date(now.getTime() - days * 24 * 60 * 60 * 1000); | |
| return products | |
| .filter(product => { | |
| const productDate = new Date(product.date); | |
| return productDate >= startDate && productDate <= now; | |
| }) | |
| .reduce((sum, product) => sum + (Math.round(product.price) * product.quantity), 0); | |
| } | |
| // Mettre à jour les graphiques | |
| function updateCharts() { | |
| // Graphique des ventes par mois | |
| const monthlyData = getMonthlySalesData(); | |
| const monthlyCtx = document.getElementById('monthlyChart').getContext('2d'); | |
| new Chart(monthlyCtx, { | |
| type: 'bar', | |
| data: { | |
| labels: monthlyData.labels, | |
| datasets: [{ | |
| label: 'Ventes (GNF)', | |
| data: monthlyData.values, | |
| backgroundColor: 'rgba(99, 102, 241, 0.5)', | |
| borderColor: 'rgba(99, 102, 241, 1)', | |
| borderWidth: 1 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| scales: { | |
| y: { | |
| beginAtZero: true | |
| } | |
| } | |
| } | |
| }); | |
| // Graphique des types de transactions | |
| const typeData = getTypeData(); | |
| const typeCtx = document.getElementById('typeChart').getContext('2d'); | |
| new Chart(typeCtx, { | |
| type: 'doughnut', | |
| data: { | |
| labels: typeData.labels, | |
| datasets: [{ | |
| data: typeData.values, | |
| backgroundColor: [ | |
| 'rgba(34, 197, 94, 0.5)', | |
| 'rgba(239, 68, 68, 0.5)' | |
| ], | |
| borderColor: [ | |
| 'rgba(34, 197, 94, 1)', | |
| 'rgba(239, 68, 68, 1)' | |
| ], | |
| borderWidth: 1 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false | |
| } | |
| }); | |
| } | |
| // Obtenir les données de ventes par mois | |
| function getMonthlySalesData() { | |
| const months = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']; | |
| const sales = new Array(12).fill(0); | |
| products.forEach(product => { | |
| const monthIndex = months.indexOf(product.month); | |
| if (monthIndex !== -1) { | |
| sales[monthIndex] += Math.round(product.price) * product.quantity; | |
| } | |
| }); | |
| return { | |
| labels: months, | |
| values: sales | |
| }; | |
| } | |
| // Obtenir les données de types de transactions | |
| function getTypeData() { | |
| const typeCounts = { | |
| 'Entrée': 0, | |
| 'Sortie': 0 | |
| }; | |
| products.forEach(product => { | |
| if (typeCounts.hasOwnProperty(product.type)) { | |
| typeCounts[product.type] += Math.round(product.price) * product.quantity; | |
| } | |
| }); | |
| return { | |
| labels: Object.keys(typeCounts), | |
| values: Object.values(typeCounts) | |
| }; | |
| } | |
| // Afficher la liste des produits | |
| function renderProductList(filteredProducts = null) { | |
| const productList = document.getElementById('productList'); | |
| const dataToShow = filteredProducts || products; | |
| if (dataToShow.length === 0) { | |
| productList.innerHTML = ` | |
| <tr> | |
| <td colspan="8" class="px-6 py-4 text-center text-gray-500"> | |
| Aucun produit trouvé | |
| </td> | |
| </tr> | |
| `; | |
| return; | |
| } | |
| productList.innerHTML = dataToShow.map((product, index) => ` | |
| <tr class="hover:bg-gray-50"> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${product.id}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${product.name}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${Math.round(product.price)} GNF</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${product.quantity}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${product.date}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${product.month}</td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full | |
| ${product.type === 'Entrée' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}"> | |
| ${product.type} | |
| </span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${product.stock}</td> | |
| </tr> | |
| `).join(''); | |
| feather.replace(); | |
| } | |
| // Filtrer les produits | |
| function filterProducts() { | |
| const searchTerm = document.getElementById('searchInput').value.toLowerCase(); | |
| const filtered = products.filter(product => | |
| product.id.toLowerCase().includes(searchTerm) || | |
| product.name.toLowerCase().includes(searchTerm) || | |
| product.month.toLowerCase().includes(searchTerm) || | |
| product.type.toLowerCase().includes(searchTerm) | |
| ); | |
| renderProductList(filtered); | |
| } | |
| // Imprimer les données | |
| function printData() { | |
| window.print(); | |
| } | |
| </script> | |
| </body> | |
| </html> |