test5 / index.html
gtkh's picture
Add 2 files
74c89b8 verified
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Outil de Détection de Fraudes</title>
<script src="https://cdn.tailwindcss.com"></script>
<!-- Bootstrap CSS via CDN -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<!-- Font Awesome for icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f8f9fa;
}
#sidebar {
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 220px;
background: linear-gradient(180deg, #2c3e50 0%, #1a1a2e 100%);
color: #fff;
padding-top: 20px;
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
}
#sidebar .nav-link {
color: #e2e8f0;
padding: 12px 20px;
margin: 2px 0;
border-radius: 4px;
transition: all 0.3s ease;
}
#sidebar .nav-link:hover {
background: rgba(255,255,255,0.1);
transform: translateX(5px);
}
#sidebar .nav-link.active {
background: rgba(255,255,255,0.15);
border-left: 4px solid #4299e1;
}
#content {
margin-left: 240px;
padding: 30px;
background-color: white;
min-height: 100vh;
box-shadow: -2px 0 10px rgba(0,0,0,0.05);
}
.section {
display: none;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Enhanced table styling */
.enhanced-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
margin: 20px 0;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
border-radius: 8px;
overflow: hidden;
}
.enhanced-table thead th {
background-color: #2c3e50;
color: white;
padding: 12px 15px;
text-align: left;
font-weight: 600;
position: sticky;
top: 0;
}
.enhanced-table tbody tr {
transition: all 0.2s ease;
}
.enhanced-table tbody tr:hover {
background-color: rgba(66, 153, 225, 0.1);
}
.enhanced-table tbody td {
padding: 12px 15px;
border-bottom: 1px solid #e2e8f0;
vertical-align: middle;
}
.enhanced-table tbody tr:last-child td {
border-bottom: none;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #cbd5e0;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #a0aec0;
}
/* Tab styling */
.nav-tabs .nav-link {
color: #4a5568;
font-weight: 500;
border: none;
padding: 12px 20px;
margin-right: 5px;
}
.nav-tabs .nav-link.active {
color: #2c3e50;
border-bottom: 3px solid #2c3e50;
background-color: transparent;
}
.nav-tabs .nav-link:hover:not(.active) {
border-bottom: 3px solid #e2e8f0;
}
/* Button styling */
.btn {
transition: all 0.2s ease;
font-weight: 500;
padding: 8px 16px;
}
.btn-primary {
background-color: #2c3e50;
border-color: #2c3e50;
}
.btn-primary:hover {
background-color: #1a1a2e;
border-color: #1a1a2e;
transform: translateY(-2px);
}
/* Card styling */
.card {
border: none;
border-radius: 8px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
/* Responsive adjustments */
@media (max-width: 992px) {
#sidebar {
width: 180px;
}
#content {
margin-left: 200px;
}
}
@media (max-width: 768px) {
#sidebar {
width: 100%;
height: auto;
position: relative;
}
#content {
margin-left: 0;
}
}
</style>
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css">
</head>
<body>
<div class="container-fluid">
<div class="row">
<!-- Menu latéral -->
<nav id="sidebar" class="col-md-2 d-none d-md-block sidebar">
<div class="sidebar-sticky">
<div class="text-center mb-4">
<h4 class="font-bold text-xl text-white">IRS Enquête</h4>
<p class="text-xs text-gray-300">Outil de Détection de Fraudes</p>
</div>
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="#" onclick="showSection('home')"><i class="fas fa-home mr-2"></i>Accueil</a></li>
<li class="nav-item"><a class="nav-link" href="#" onclick="showSection('import')"><i class="fas fa-file-import mr-2"></i>Importer CSV</a></li>
<li class="nav-item"><a class="nav-link" href="#" onclick="showSection('filter')"><i class="fas fa-filter mr-2"></i>Filtrer & Rapport</a></li>
<li class="nav-item"><a class="nav-link active" href="#" onclick="showSection('lecture')"><i class="fas fa-book-reader mr-2"></i>Lecture</a></li>
<li class="nav-item"><a class="nav-link" href="#" onclick="showSection('export')"><i class="fas fa-file-export mr-2"></i>Exporter Rapport</a></li>
<li class="nav-item"><a class="nav-link" href="#" onclick="showSection('favorites')"><i class="fas fa-star mr-2"></i>Favoris</a></li>
<li class="nav-item"><a class="nav-link" href="#" onclick="showSection('logs')"><i class="fas fa-clipboard-list mr-2"></i>Logs</a></li>
</ul>
</div>
</nav>
<!-- Contenu principal -->
<main id="content" class="col-md-9 ml-sm-auto col-lg-10 px-4">
<!-- Section Accueil -->
<div id="section-home" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Accueil</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-home"></i></span>
</div>
<div class="bg-white rounded-lg shadow p-6">
<p class="text-gray-700">Bienvenue dans l'outil de détection de fraudes IRS Enquête. Utilisez le menu pour naviguer entre les fonctionnalités.</p>
<div class="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
<h3 class="font-semibold text-blue-800"><i class="fas fa-file-import mr-2"></i>Importation</h3>
<p class="text-sm text-blue-600 mt-2">Importez vos fichiers CSV pour commencer l'analyse.</p>
</div>
<div class="bg-green-50 p-4 rounded-lg border border-green-100">
<h3 class="font-semibold text-green-800"><i class="fas fa-filter mr-2"></i>Filtrage</h3>
<p class="text-sm text-green-600 mt-2">Filtrez les données selon différents critères.</p>
</div>
<div class="bg-purple-50 p-4 rounded-lg border border-purple-100">
<h3 class="font-semibold text-purple-800"><i class="fas fa-chart-bar mr-2"></i>Analyse</h3>
<p class="text-sm text-purple-600 mt-2">Visualisez les résultats sous forme de tableaux et graphiques.</p>
</div>
</div>
</div>
</div>
<!-- Section Import CSV -->
<div id="section-import" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Importer CSV</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-file-import"></i></span>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="form-group">
<label for="csvInput" class="font-medium text-gray-700">Collez le contenu du CSV (séparateur ;) :</label>
<textarea class="form-control mt-1" id="csvInput" rows="10" style="border-radius: 6px; border: 1px solid #e2e8f0;"></textarea>
</div>
<button class="btn btn-primary mt-3" onclick="importCSV()">
<i class="fas fa-upload mr-2"></i>Importer
</button>
<div id="importResult" class="mt-4"></div>
</div>
</div>
<!-- Section Filtrer & Rapport -->
<div id="section-filter" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Filtrer & Générer Rapport</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-filter"></i></span>
</div>
<div class="bg-white rounded-lg shadow p-6">
<form id="filterForm">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="form-group">
<label for="dateDebut" class="font-medium text-gray-700">Date début :</label>
<input type="date" class="form-control mt-1" id="dateDebut" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-group">
<label for="dateFin" class="font-medium text-gray-700">Date fin :</label>
<input type="date" class="form-control mt-1" id="dateFin" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
</div>
<div class="form-group mt-4">
<label for="filterText" class="font-medium text-gray-700">Filtrer par Raison (séparez plusieurs critères par ";") :</label>
<input type="text" class="form-control mt-1" id="filterText" placeholder="ex: Paiement facture;Transfère" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-group mt-4">
<label for="filterIndicator" class="font-medium text-gray-700">Filtrer par Indicateur (Initiateur) :</label>
<input type="text" class="form-control mt-1" id="filterIndicator" placeholder="ex: 68484" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-group mt-4">
<label class="font-medium text-gray-700">Filtrer par Montant :</label>
<div class="space-y-3 mt-2">
<div class="form-check">
<input class="form-check-input" type="radio" name="amountFilterMode" id="amountNone" value="none" checked>
<label class="form-check-label ml-2 text-gray-700" for="amountNone">Aucun filtre</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="amountFilterMode" id="amountGreaterRadio" value="greater">
<label class="form-check-label ml-2 text-gray-700" for="amountGreaterRadio">Montant supérieur à</label>
<input type="number" class="form-control mt-1 ml-4" id="amountGreater" placeholder="Valeur" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="amountFilterMode" id="amountLessRadio" value="less">
<label class="form-check-label ml-2 text-gray-700" for="amountLessRadio">Montant inférieur à</label>
<input type="number" class="form-control mt-1 ml-4" id="amountLess" placeholder="Valeur" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="amountFilterMode" id="amountBetweenRadio" value="between">
<label class="form-check-label ml-2 text-gray-700" for="amountBetweenRadio">Montant entre</label>
<div class="flex items-center mt-1 ml-4">
<input type="number" class="form-control mr-2" id="amountMin" placeholder="Min" style="border-radius: 6px; border: 1px solid #e2e8f0;">
<span class="text-gray-500 mx-1">et</span>
<input type="number" class="form-control ml-2" id="amountMax" placeholder="Max" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-3 mt-6">
<button type="button" class="btn btn-primary" onclick="generateReport()">
<i class="fas fa-file-alt mr-2"></i>Générer Rapport complet
</button>
<button type="button" class="btn btn-danger" onclick="resetReportsUI()">
<i class="fas fa-redo mr-2"></i>Remise à zéro des rapports
</button>
</div>
</form>
<div id="reportResult" class="mt-6"></div>
</div>
</div>
<!-- Section Lecture -->
<div id="section-lecture" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Lecture des Rapports</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-book-reader"></i></span>
</div>
<!-- Onglets -->
<ul class="nav nav-tabs" id="lectureTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="tab-rapport" data-toggle="tab" href="#view-rapport" role="tab">
<i class="fas fa-file-alt mr-2"></i>Rapport
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tab-group" data-toggle="tab" href="#view-group" role="tab">
<i class="fas fa-users mr-2"></i>Par groupe
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tab-indicator" data-toggle="tab" href="#view-indicator" role="tab">
<i class="fas fa-chart-line mr-2"></i>Par indicateur
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tab-graphs" data-toggle="tab" href="#view-graphs" role="tab">
<i class="fas fa-chart-pie mr-2"></i>Graphiques
</a>
</li>
</ul>
<div class="tab-content bg-white rounded-b-lg rounded-tr-lg shadow p-6" id="lectureTabsContent">
<div class="tab-pane fade show active" id="view-rapport" role="tabpanel">
<button class="btn btn-info mb-4" onclick="loadReportData()">
<i class="fas fa-sync-alt mr-2"></i>Rafraîchir Rapport
</button>
<div id="reportDataDiv" class="mt-2 overflow-x-auto">
<!-- Table will be inserted here -->
</div>
</div>
<div class="tab-pane fade" id="view-group" role="tabpanel">
<button class="btn btn-info mb-4" onclick="loadGroupData()">
<i class="fas fa-sync-alt mr-2"></i>Rafraîchir Par groupe
</button>
<div id="groupDataDiv" class="mt-2 overflow-x-auto">
<!-- Table will be inserted here -->
</div>
</div>
<div class="tab-pane fade" id="view-indicator" role="tabpanel">
<button class="btn btn-info mb-4" onclick="loadIndicatorData()">
<i class="fas fa-sync-alt mr-2"></i>Rafraîchir Par indicateur
</button>
<div id="indicatorDataDiv" class="mt-2 overflow-x-auto">
<!-- Table will be inserted here -->
</div>
</div>
<div class="tab-pane fade" id="view-graphs" role="tabpanel">
<button class="btn btn-info mb-4" onclick="loadGraphs()">
<i class="fas fa-sync-alt mr-2"></i>Rafraîchir Graphiques
</button>
<div id="graphsDiv" class="mt-2">
<!-- Graphs will be inserted here -->
</div>
</div>
</div>
</div>
<!-- Section Export -->
<div id="section-export" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Exporter Rapport</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-file-export"></i></span>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<button class="btn btn-secondary" onclick="exportReportsCSVZipUI()">
<i class="fas fa-file-csv mr-2"></i>Exporter Rapport en CSV (ZIP)
</button>
<button class="btn btn-secondary" onclick="exportReportsPDFZipUI()">
<i class="fas fa-file-pdf mr-2"></i>Exporter Rapport en PDF (ZIP)
</button>
</div>
<div id="exportResult" class="mt-4"></div>
</div>
</div>
<!-- Section Favoris -->
<div id="section-favorites" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Favoris</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-star"></i></span>
</div>
<div class="bg-white rounded-lg shadow p-6">
<form id="favoriteForm">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="form-group">
<label for="favName" class="font-medium text-gray-700">Nom du favori :</label>
<input type="text" class="form-control mt-1" id="favName" required style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-group">
<label for="favDateDebut" class="font-medium text-gray-700">Date début :</label>
<input type="date" class="form-control mt-1" id="favDateDebut" required style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-group">
<label for="favDateFin" class="font-medium text-gray-700">Date fin :</label>
<input type="date" class="form-control mt-1" id="favDateFin" required style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-group">
<label for="favFilterText" class="font-medium text-gray-700">Filtrer par Raison :</label>
<input type="text" class="form-control mt-1" id="favFilterText" placeholder="ex: Paiement facture;Transfère" required style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
</div>
<div class="form-group mt-4">
<label class="font-medium text-gray-700">Filtrer par Montant :</label>
<div class="space-y-3 mt-2">
<div class="form-check">
<input class="form-check-input" type="radio" name="favAmountFilterMode" id="favAmountNone" value="none" checked>
<label class="form-check-label ml-2 text-gray-700" for="favAmountNone">Aucun filtre</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="favAmountFilterMode" id="favAmountGreater" value="greater">
<label class="form-check-label ml-2 text-gray-700" for="favAmountGreater">Montant supérieur à</label>
<input type="number" class="form-control mt-1 ml-4" id="favAmountGreaterVal" placeholder="Valeur" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="favAmountFilterMode" id="favAmountLess" value="less">
<label class="form-check-label ml-2 text-gray-700" for="favAmountLess">Montant inférieur à</label>
<input type="number" class="form-control mt-1 ml-4" id="favAmountLessVal" placeholder="Valeur" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="favAmountFilterMode" id="favAmountBetween" value="between">
<label class="form-check-label ml-2 text-gray-700" for="favAmountBetween">Montant entre</label>
<div class="flex items-center mt-1 ml-4">
<input type="number" class="form-control mr-2" id="favAmountMin" placeholder="Min" style="border-radius: 6px; border: 1px solid #e2e8f0;">
<span class="text-gray-500 mx-1">et</span>
<input type="number" class="form-control ml-2" id="favAmountMax" placeholder="Max" style="border-radius: 6px; border: 1px solid #e2e8f0;">
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-primary mt-4" onclick="saveFavorite()">
<i class="fas fa-save mr-2"></i>Enregistrer Favori
</button>
</form>
<hr class="my-6 border-gray-200">
<div class="flex items-center justify-between mb-4">
<h4 class="font-bold text-lg text-gray-800">Liste des Favoris</h4>
<button class="btn btn-secondary" onclick="loadFavorites()">
<i class="fas fa-sync-alt mr-2"></i>Charger Favoris
</button>
</div>
<div id="favoritesList" class="overflow-x-auto"></div>
</div>
</div>
<!-- Section Logs -->
<div id="section-logs" class="section">
<div class="flex items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Logs</h2>
<span class="ml-2 text-blue-500"><i class="fas fa-clipboard-list"></i></span>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between mb-4">
<h4 class="font-bold text-lg text-gray-800">Historique des activités</h4>
<button class="btn btn-secondary" onclick="loadLogs()">
<i class="fas fa-sync-alt mr-2"></i>Charger Logs
</button>
</div>
<div id="logsList" class="overflow-x-auto"></div>
</div>
</div>
</main>
</div>
</div>
<!-- Bootstrap JS et dépendances -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<!-- DataTables JS -->
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
<script>
// Affichage des notifications
function showNotification(elementId, message, type) {
var alertClass = {
'success': 'bg-green-100 border-green-400 text-green-700',
'danger': 'bg-red-100 border-red-400 text-red-700',
'info': 'bg-blue-100 border-blue-400 text-blue-700',
'warning': 'bg-yellow-100 border-yellow-400 text-yellow-700'
};
var notification = document.createElement('div');
notification.className = `border-l-4 p-4 mb-4 rounded ${alertClass[type]}`;
notification.innerHTML = `
<div class="flex items-center">
<div class="flex-shrink-0">
${type === 'success' ? '<i class="fas fa-check-circle text-green-500"></i>' :
type === 'danger' ? '<i class="fas fa-exclamation-circle text-red-500"></i>' :
type === 'info' ? '<i class="fas fa-info-circle text-blue-500"></i>' :
'<i class="fas fa-exclamation-triangle text-yellow-500"></i>'}
</div>
<div class="ml-3">
<p class="text-sm">${message}</p>
</div>
<div class="ml-auto pl-3">
<button type="button" class="text-gray-500 hover:text-gray-700" onclick="this.parentElement.parentElement.remove()">
<i class="fas fa-times"></i>
</button>
</div>
</div>
`;
document.getElementById(elementId).appendChild(notification);
}
// Afficher une section et masquer les autres
function showSection(section) {
var sections = document.querySelectorAll('.section');
sections.forEach(function(sec) { sec.style.display = 'none'; });
document.getElementById('section-' + section).style.display = 'block';
// Update active state in sidebar
document.querySelectorAll('#sidebar .nav-link').forEach(function(link) {
link.classList.remove('active');
});
document.querySelector(`#sidebar .nav-link[onclick="showSection('${section}')"]`).classList.add('active');
}
showSection('home');
// Import CSV
function importCSV() {
var csvText = document.getElementById('csvInput').value;
google.script.run.withSuccessHandler(function(response) {
showNotification('importResult', response, "success");
}).withFailureHandler(function(error) {
showNotification('importResult', "Erreur : " + error.message, "danger");
}).importCSVData(csvText);
}
// Générer le rapport complet
function generateReport() {
var criteria = {
dateDebut: document.getElementById('dateDebut').value,
dateFin: document.getElementById('dateFin').value,
filterText: document.getElementById('filterText').value,
filterIndicator: document.getElementById('filterIndicator').value,
amountFilterMode: document.querySelector('input[name="amountFilterMode"]:checked').value,
amountGreater: document.getElementById('amountGreater').value,
amountLess: document.getElementById('amountLess').value,
amountMin: document.getElementById('amountMin').value,
amountMax: document.getElementById('amountMax').value
};
google.script.run.withSuccessHandler(function(response) {
showNotification('reportResult', response, "success");
}).withFailureHandler(function(error) {
showNotification('reportResult', "Erreur : " + error.message, "danger");
}).filterAndGenerateReport(criteria);
}
// Réinitialiser les rapports
function resetReportsUI() {
google.script.run.withSuccessHandler(function(response) {
showNotification('reportResult', response, "info");
}).withFailureHandler(function(error) {
showNotification('reportResult', "Erreur lors de la remise à zéro : " + error.message, "danger");
}).resetReports();
}
// Export CSV ZIP
function exportReportsCSVZipUI() {
google.script.run.withSuccessHandler(function(base64Zip) {
var link = document.createElement("a");
link.href = "data:application/zip;base64," + base64Zip;
link.download = "Rapports_CSV.zip";
link.click();
showNotification('exportResult', "Export CSV (ZIP) réussi.", "success");
}).withFailureHandler(function(error) {
showNotification('exportResult', "Erreur lors de l'export CSV (ZIP) : " + error.message, "danger");
}).exportReportsCSVAsBase64();
}
// Export PDF ZIP
function exportReportsPDFZipUI() {
google.script.run.withSuccessHandler(function(base64Zip) {
var link = document.createElement("a");
link.href = "data:application/zip;base64," + base64Zip;
link.download = "Rapports_PDF.zip";
link.click();
showNotification('exportResult', "Export PDF (ZIP) réussi.", "success");
}).withFailureHandler(function(error) {
showNotification('exportResult', "Erreur lors de l'export PDF (ZIP) : " + error.message, "danger");
}).exportReportsPDFZipAsBase64();
}
// Favoris
function saveFavorite() {
var fav = {
name: document.getElementById('favName').value,
dateDebut: document.getElementById('favDateDebut').value,
dateFin: document.getElementById('favDateFin').value,
filterText: document.getElementById('favFilterText').value,
amountFilterMode: document.querySelector('input[name="favAmountFilterMode"]:checked').value,
amountGreater: document.getElementById('favAmountGreaterVal').value,
amountLess: document.getElementById('favAmountLessVal').value,
amountMin: document.getElementById('favAmountMin').value,
amountMax: document.getElementById('favAmountMax').value
};
google.script.run.withSuccessHandler(function(response) {
showNotification('favoritesList', response, "success");
loadFavorites();
}).withFailureHandler(function(error) {
showNotification('favoritesList', "Erreur : " + error.message, "danger");
}).saveFavorite(fav);
}
function loadFavorites() {
google.script.run.withSuccessHandler(function(data) {
if (!data || data.length <= 1) {
document.getElementById('favoritesList').innerHTML = '<p class="text-gray-500">Aucun favori enregistré.</p>';
return;
}
var html = '<table class="enhanced-table"><thead><tr><th>Date</th><th>Nom</th><th>Date Début</th><th>Date Fin</th><th>Filtre Raison</th><th>Mode Montant</th><th>Valeur(s)</th></tr></thead><tbody>';
for (var i = 1; i < data.length; i++) {
html += '<tr>';
for (var j = 0; j < data[i].length; j++) {
html += '<td>' + (data[i][j] || '') + '</td>';
}
html += '</tr>';
}
html += '</tbody></table>';
document.getElementById('favoritesList').innerHTML = html;
// Initialize DataTable
$('#favoritesList table').DataTable({
"pageLength": 10,
"ordering": true,
"searching": true,
"language": { "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/French.json" }
});
}).getFavorites();
}
function loadLogs() {
google.script.run.withSuccessHandler(function(data) {
if (!data || data.length <= 1) {
document.getElementById('logsList').innerHTML = '<p class="text-gray-500">Aucun log disponible.</p>';
return;
}
var html = '<table class="enhanced-table"><thead><tr><th>Date</th><th>Action</th><th>Détails</th></tr></thead><tbody>';
for (var i = 1; i < data.length; i++) {
html += '<tr>';
for (var j = 0; j < data[i].length; j++) {
html += '<td>' + (data[i][j] || '') + '</td>';
}
html += '</tr>';
}
html += '</tbody></table>';
document.getElementById('logsList').innerHTML = html;
// Initialize DataTable
$('#logsList table').DataTable({
"pageLength": 10,
"ordering": true,
"searching": true,
"language": { "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/French.json" }
});
}).getLogs();
}
// Fonctions pour la section Lecture avec DataTables pour "Rapport"
var reportDataCache = [];
function loadReportData() {
google.script.run.withSuccessHandler(function(data) {
reportDataCache = data;
var html = generateEnhancedTableHTML(reportDataCache);
document.getElementById('reportDataDiv').innerHTML = html;
$('#reportDataDiv table').DataTable({
"pageLength": 100,
"ordering": true,
"searching": true,
"language": { "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/French.json" }
});
}).getReportData();
}
function loadGroupData() {
google.script.run.withSuccessHandler(function(data) {
var html = generateEnhancedTableHTML(data);
document.getElementById('groupDataDiv').innerHTML = html;
$('#groupDataDiv table').DataTable({
"pageLength": 100,
"ordering": true,
"searching": true,
"language": { "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/French.json" }
});
}).getGroupData();
}
function loadIndicatorData() {
google.script.run.withSuccessHandler(function(data) {
var html = generateEnhancedTableHTML(data);
document.getElementById('indicatorDataDiv').innerHTML = html;
$('#indicatorDataDiv table').DataTable({
"pageLength": 100,
"ordering": true,
"searching": true,
"language": { "url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/French.json" }
});
}).getIndicatorData();
}
function generateEnhancedTableHTML(data) {
if (!data || data.length === 0) return "<div class='bg-gray-50 p-4 rounded-lg border border-gray-200 text-center text-gray-500'>Aucune donnée disponible.</div>";
var html = "<table class='enhanced-table'><thead><tr>";
// Headers
data[0].forEach(function(header) {
html += "<th class='text-left'>" + header + "</th>";
});
html += "</tr></thead><tbody>";
// Rows
for (var i = 1; i < data.length; i++) {
html += "<tr>";
data[i].forEach(function(cell) {
// Highlight potential numeric values (amounts)
if (!isNaN(parseFloat(cell)) && cell.toString().indexOf('.') !== -1) {
html += "<td class='text-right font-medium'>" + parseFloat(cell).toFixed(2) + "</td>";
} else {
html += "<td>" + (cell || '') + "</td>";
}
});
html += "</tr>";
}
html += "</tbody></table>";
return html;
}
// Fonction pour charger les graphiques dans la section Graphiques
function loadGraphs() {
google.script.run.withSuccessHandler(function(html) {
document.getElementById('graphsDiv').innerHTML = html;
}).withFailureHandler(function(error) {
showNotification('exportResult', "Erreur lors du chargement des graphiques : " + error.message, "danger");
}).getGraphsHTML();
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=gtkh/test5" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>