0% found this document useful (0 votes)
29 views101 pages

Prototype CRM

The document outlines the HTML structure and styling for a web application called EasyBank, focusing on database management. It includes various components such as a navigation bar, sidebar, loading screen, and main content area with statistics and charts. The styling utilizes Tailwind CSS and custom styles for dark/light mode, buttons, tables, and modals.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views101 pages

Prototype CRM

The document outlines the HTML structure and styling for a web application called EasyBank, focusing on database management. It includes various components such as a navigation bar, sidebar, loading screen, and main content area with statistics and charts. The styling utilizes Tailwind CSS and custom styles for dark/light mode, buttons, tables, and modals.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 101

<!

DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-


scale=1.0">

<title>EasyBank - Database Management</title>

<!-- Tailwind CSS -->

<script src="https://cdn.tailwindcss.com"></script>

<!-- Chart.js for visualizations -->

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<!-- Font Awesome for icons -->

<script src="https://kit.fontawesome.com/3b5b23580e.js"
crossorigin="anonymous"></script>

<style>

/* Custom styles */

:root {

--primary-color: #5D5CDE;

--secondary-color: #4CAF50; /* Green */

--dark-color: #181818;

--light-color: #FFFFFF;

/* Toggle dark/light mode based on system preference */

@media (prefers-color-scheme: dark) {

.bg-app-primary {

background-color: var(--dark-color);
color: var(--light-color);

.bg-app-secondary {

background-color: #222222;

color: var(--light-color);

.card-bg {

background-color: #2d2d2d;

color: var(--light-color);

.text-app-primary {

color: var(--light-color);

.border-app {

border-color: #333333;

@media (prefers-color-scheme: light) {

.bg-app-primary {

background-color: var(--light-color);

color: var(--dark-color);

.bg-app-secondary {

background-color: #f8f9fa;

color: var(--dark-color);

}
.card-bg {

background-color: white;

color: var(--dark-color);

.text-app-primary {

color: var(--dark-color);

.border-app {

border-color: #e5e7eb;

.btn-primary {

background-color: var(--secondary-color);

color: white;

transition: all 0.3s;

.btn-primary:hover {

opacity: 0.9;

.btn-secondary {

background-color: #333;

color: white;

transition: all 0.3s;

.btn-secondary:hover {

opacity: 0.9;
}

.notification-badge {

position: absolute;

top: -5px;

right: -5px;

background-color: red;

color: white;

border-radius: 50%;

width: 20px;

height: 20px;

font-size: 12px;

display: flex;

align-items: center;

justify-content: center;

/* Animation for loading */

@keyframes spin {

0% { transform: rotate(0deg); }

100% { transform: rotate(360deg); }

.loading-spinner {

border: 4px solid rgba(0, 0, 0, 0.1);

border-left-color: var(--secondary-color);

border-radius: 50%;

width: 24px;
height: 24px;

animation: spin 1s linear infinite;

margin: 0 auto;

/* Table styles */

.data-table {

width: 100%;

border-collapse: collapse;

.data-table th {

background-color: var(--secondary-color);

color: white;

padding: 10px;

text-align: left;

position: sticky;

top: 0;

z-index: 10;

.data-table td {

padding: 10px;

border-bottom: 1px solid #ddd;

.data-table tr:hover {

background-color: rgba(76, 175, 80, 0.1);

}
/* Modal styles */

.modal {

display: none;

position: fixed;

z-index: 1000;

left: 0;

top: 0;

width: 100%;

height: 100%;

overflow: auto;

background-color: rgba(0,0,0,0.5);

.modal-content {

background-color: var(--light-color);

color: var(--dark-color);

margin: 10% auto;

padding: 20px;

border-radius: 8px;

width: 80%;

max-width: 700px;

box-shadow: 0 4px 8px rgba(0,0,0,0.1);

position: relative;

@media (prefers-color-scheme: dark) {

.modal-content {

background-color: #222;

color: white;
}

.close-modal {

position: absolute;

right: 15px;

top: 10px;

font-size: 24px;

font-weight: bold;

cursor: pointer;

/* Client card styles */

.client-card {

border-left: 4px solid var(--secondary-color);

transition: transform 0.2s;

.client-card:hover {

transform: translateY(-2px);

/* Status badges */

.status-badge {

padding: 4px 8px;

border-radius: 4px;

font-size: 12px;

font-weight: bold;

text-transform: uppercase;
}

.status-pending {

background-color: #FFC107;

color: #333;

.status-confirmed {

background-color: #4CAF50;

color: white;

.status-rejected {

background-color: #F44336;

color: white;

/* Call tracking badges */

.call-badge {

display: inline-block;

margin-right: 5px;

width: 24px;

height: 24px;

border-radius: 50%;

text-align: center;

line-height: 24px;

font-size: 12px;

.call-pending {

background-color: #e0e0e0;
color: #333;

.call-scheduled {

background-color: #FFC107;

color: #333;

.call-completed {

background-color: #4CAF50;

color: white;

.call-missed {

background-color: #F44336;

color: white;

/* Logo styling */

.logo {

height: 40px;

/* Custom scrollbar */

::-webkit-scrollbar {

width: 8px;

::-webkit-scrollbar-track {

background: #f1f1f1;

}
::-webkit-scrollbar-thumb {

background: var(--secondary-color);

border-radius: 4px;

::-webkit-scrollbar-thumb:hover {

background: #388e3c;

</style>

</head>

<body class="bg-app-primary min-h-screen">

<!-- Loading Screen -->

<div id="loading-screen" class="fixed inset-0 flex items-center justify-


center bg-app-primary z-50">

<div class="text-center">

<div class="loading-spinner mx-auto mb-4"></div>

<p class="text-lg">Chargement de la plateforme EasyBank...</p>

</div>

</div>

<!-- Navigation -->

<nav class="bg-app-secondary shadow-md">

<div class="container mx-auto px-4 py-3">

<div class="flex justify-between items-center">

<div class="flex items-center">

<!-- EasyBank Logo -->

<div class="flex items-center">

<svg class="h-10 w-10 mr-2" viewBox="0 0 100 100">


<rect width="100" height="100" rx="10"
fill="#4CAF50"/>

<text x="50%" y="50%" dominant-baseline="middle" text-


anchor="middle" fill="white" font-size="40" font-weight="bold">EB</text>

</svg>

<span class="text-xl font-bold">EasyBank</span>

</div>

</div>

<div class="flex items-center space-x-4">

<button id="notifications-btn" class="relative p-2 rounded-full


hover:bg-gray-200 dark:hover:bg-gray-700 transition">

<i class="fas fa-bell"></i>

<span id="notification-count" class="notification-badge


hidden">0</span>

</button>

<button id="user-menu-btn" class="flex items-center space-x-2


p-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 transition">

<i class="fas fa-user-circle text-xl"></i>

<span>Admin</span>

</button>

</div>

</div>

</div>

</nav>

<!-- Main Content -->

<div class="container mx-auto px-4 py-8">

<!-- Sidebar and Main Content Wrapper -->


<div class="flex flex-col md:flex-row gap-6">

<!-- Sidebar -->

<div class="w-full md:w-1/4 lg:w-1/5">

<div class="card-bg rounded-lg shadow p-4 mb-6">

<h2 class="text-lg font-semibold mb-4">Navigation</h2>

<ul class="space-y-2">

<li>

<a href="#dashboard" class="nav-link flex items-center p-


2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition">

<i class="fas fa-tachometer-alt w-6"></i>

<span>Tableau de bord</span>

</a>

</li>

<li>

<a href="#employe-titulaire" class="nav-link flex items-


center p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition">

<i class="fas fa-user-tie w-6"></i>

<span>Employé titulaire</span>

</a>

</li>

<li>

<a href="#employe-non-titulaire" class="nav-link flex


items-center p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700
transition">

<i class="fas fa-user w-6"></i>

<span>Employé non titulaire</span>

</a>

</li>
<li>

<a href="#profession-lib-fisc" class="nav-link flex items-


center p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition">

<i class="fas fa-briefcase w-6"></i>

<span>Profession libérale avec IF</span>

</a>

</li>

<li>

<a href="#profession-lib-non-fisc" class="nav-link flex


items-center p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700
transition">

<i class="fas fa-briefcase w-6"></i>

<span>Profession libérale sans IF</span>

</a>

</li>

<li>

<a href="#chomeur" class="nav-link flex items-center p-2


rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition">

<i class="fas fa-user-clock w-6"></i>

<span>Chomeur</span>

</a>

</li>

<li>

<a href="#resident-etranger" class="nav-link flex items-


center p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition">

<i class="fas fa-globe w-6"></i>

<span>Résident à l'étranger</span>

</a>
</li>

<li>

<a href="#problemes" class="nav-link flex items-center p-


2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition">

<i class="fas fa-exclamation-triangle w-6"></i>

<span>Déclarations de problèmes</span>

</a>

</li>

</ul>

</div>

<!-- Quick Stats Card -->

<div class="card-bg rounded-lg shadow p-4">

<h2 class="text-lg font-semibold mb-4">Statistiques


Rapides</h2>

<div class="space-y-3">

<div>

<p class="text-sm text-gray-500 dark:text-gray-400">Total


des clients</p>

<p id="total-clients" class="text-xl font-bold">0</p>

</div>

<div>

<p class="text-sm text-gray-500 dark:text-gray-


400">Clients confirmés</p>

<p id="confirmed-clients" class="text-xl font-bold">0</p>

</div>

<div>
<p class="text-sm text-gray-500 dark:text-gray-400">En
attente</p>

<p id="pending-clients" class="text-xl font-bold">0</p>

</div>

<div>

<p class="text-sm text-gray-500 dark:text-gray-


400">Rejetés</p>

<p id="rejected-clients" class="text-xl font-bold">0</p>

</div>

</div>

</div>

</div>

<!-- Main Content Area -->

<div class="w-full md:w-3/4 lg:w-4/5">

<!-- Dynamic Content Section -->

<div id="content-area">

<!-- Dashboard Section -->

<section id="dashboard" class="active-section">

<h1 class="text-2xl font-bold mb-6">Tableau de bord</h1>

<!-- Cards Row -->

<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-


4 mb-6">

<!-- Daily Submissions Card -->

<div class="card-bg rounded-lg shadow p-4">

<div class="flex items-start justify-between">

<div>
<p class="text-sm text-gray-500 dark:text-gray-
400">Soumissions Quotidiennes</p>

<p id="daily-submissions" class="text-2xl font-


bold">0</p>

</div>

<div class="rounded-full bg-green-100 p-2">

<i class="fas fa-file-alt text-green-500"></i>

</div>

</div>

<p class="text-xs text-gray-500 mt-2">

<span id="daily-submissions-change" class="font-


medium text-green-500">+0%</span>

par rapport à hier

</p>

</div>

<!-- Monthly Submissions -->

<div class="card-bg rounded-lg shadow p-4">

<div class="flex items-start justify-between">

<div>

<p class="text-sm text-gray-500 dark:text-gray-


400">Soumissions Mensuelles</p>

<p id="monthly-submissions" class="text-2xl font-


bold">0</p>

</div>

<div class="rounded-full bg-blue-100 p-2">

<i class="fas fa-calendar-alt text-blue-500"></i>

</div>
</div>

<p class="text-xs text-gray-500 mt-2">

<span id="monthly-submissions-change" class="font-


medium text-green-500">+0%</span>

par rapport au mois dernier

</p>

</div>

<!-- Confirmed Clients Card -->

<div class="card-bg rounded-lg shadow p-4">

<div class="flex items-start justify-between">

<div>

<p class="text-sm text-gray-500 dark:text-gray-


400">Clients Confirmés Aujourd'hui</p>

<p id="daily-confirmed" class="text-2xl font-


bold">0</p>

</div>

<div class="rounded-full bg-green-100 p-2">

<i class="fas fa-check-circle text-green-500"></i>

</div>

</div>

<p class="text-xs text-gray-500 mt-2">

<span id="daily-confirmed-change" class="font-


medium text-green-500">+0%</span>

par rapport à hier

</p>

</div>
<!-- Monthly Confirmed Card -->

<div class="card-bg rounded-lg shadow p-4">

<div class="flex items-start justify-between">

<div>

<p class="text-sm text-gray-500 dark:text-gray-


400">Clients Confirmés ce Mois</p>

<p id="monthly-confirmed" class="text-2xl font-


bold">0</p>

</div>

<div class="rounded-full bg-purple-100 p-2">

<i class="fas fa-users text-purple-500"></i>

</div>

</div>

<p class="text-xs text-gray-500 mt-2">

<span id="monthly-confirmed-change" class="font-


medium text-green-500">+0%</span>

par rapport au mois dernier

</p>

</div>

</div>

<!-- Charts and Tables Row -->

<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">

<!-- Monthly Submissions Chart -->

<div class="card-bg rounded-lg shadow p-4">

<div class="flex justify-between items-center mb-4">

<h2 class="text-lg font-semibold">Soumissions par


Mois</h2>
<div class="flex space-x-2">

<button id="monthly-chart-btn" class="bg-green-


500 text-white px-3 py-1 rounded text-sm">Mensuel</button>

<button id="weekly-chart-btn" class="bg-gray-300


text-gray-700 px-3 py-1 rounded text-sm">Hebdomadaire</button>

</div>

</div>

<div class="h-64">

<canvas id="submissions-chart"></canvas>

</div>

</div>

<!-- Client Type Distribution Chart -->

<div class="card-bg rounded-lg shadow p-4">

<h2 class="text-lg font-semibold mb-4">Distribution des


Types de Clients</h2>

<div class="h-64">

<canvas id="client-types-chart"></canvas>

</div>

</div>

</div>

<!-- Additional Chart Row -->

<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">

<!-- Confirmed Clients Chart -->

<div class="card-bg rounded-lg shadow p-4">

<div class="flex justify-between items-center mb-4">


<h2 class="text-lg font-semibold">Clients
Confirmés</h2>

<div class="flex space-x-2">

<button id="monthly-confirmed-btn" class="bg-


green-500 text-white px-3 py-1 rounded text-sm">Mensuel</button>

<button id="daily-confirmed-btn" class="bg-gray-


300 text-gray-700 px-3 py-1 rounded text-sm">Quotidien</button>

</div>

</div>

<div class="h-64">

<canvas id="confirmed-chart"></canvas>

</div>

</div>

<!-- Client Status Distribution -->

<div class="card-bg rounded-lg shadow p-4">

<h2 class="text-lg font-semibold mb-4">Statut des


Clients</h2>

<div class="h-64">

<canvas id="client-status-chart"></canvas>

</div>

</div>

</div>

<!-- Recent Activity Table -->

<div class="card-bg rounded-lg shadow p-4">

<h2 class="text-lg font-semibold mb-4">Activité


Récente</h2>
<div class="overflow-x-auto">

<table class="data-table">

<thead>

<tr>

<th>Date</th>

<th>Nom</th>

<th>Téléphone</th>

<th>Type</th>

<th>Statut</th>

<th>Action</th>

</tr>

</thead>

<tbody id="recent-activity">

<tr>

<td colspan="6" class="text-center py-


4">Chargement des données...</td>

</tr>

</tbody>

</table>

</div>

</div>

</section>

<!-- Employé Titulaire Section -->

<section id="employe-titulaire" class="hidden">

<div class="flex justify-between items-center mb-6">

<h1 class="text-2xl font-bold">Employé Titulaire</h1>


<div class="flex space-x-2">

<div class="relative">

<input type="text" id="search-employe-titulaire"


placeholder="Rechercher..." class="px-4 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500 text-base">

<i class="fas fa-search absolute right-3 top-3 text-


gray-400"></i>

</div>

<select id="filter-employe-titulaire" class="px-4 py-2


rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500 text-base">

<option value="all">Tous les statuts</option>

<option value="en-attente">En attente</option>

<option value="confirme">Confirmé</option>

<option value="rejete">Rejeté</option>

</select>

</div>

</div>

<!-- Tracking System Introduction -->

<div class="card-bg rounded-lg shadow p-4 mb-6">

<h2 class="text-lg font-semibold mb-2">Système de suivi


des appels</h2>

<div class="flex flex-wrap gap-3 mb-2">

<div class="flex items-center">

<span class="call-badge call-pending


mr-2">1</span>

<span>En attente</span>

</div>
<div class="flex items-center">

<span class="call-badge call-scheduled


mr-2">1</span>

<span>Programmé</span>

</div>

<div class="flex items-center">

<span class="call-badge call-completed


mr-2">1</span>

<span>Complété</span>

</div>

<div class="flex items-center">

<span class="call-badge call-missed mr-2">1</span>

<span>Manqué</span>

</div>

</div>

<p class="text-sm text-gray-600 dark:text-gray-400">

Le système planifie automatiquement les appels de suivi


:

<strong>1er appel</strong> à la date de soumission,

<strong>2ème appel</strong> 2 jours après,

<strong>3ème appel</strong> 5 jours après le second.

</p>

</div>

<!-- Client Cards -->

<div id="employe-titulaire-list" class="grid grid-cols-1


md:grid-cols-2 xl:grid-cols-3 gap-4">
<div class="card-bg rounded-lg shadow p-4 col-span-full
text-center">

<div class="loading-spinner mx-auto mb-4"></div>

<p class="text-lg">Chargement des clients...</p>

</div>

</div>

</section>

<!-- Employé Non Titulaire Section -->

<section id="employe-non-titulaire" class="hidden">

<div class="flex justify-between items-center mb-6">

<h1 class="text-2xl font-bold">Employé Non


Titulaire</h1>

<div class="flex space-x-2">

<div class="relative">

<input type="text" id="search-employe-non-titulaire"


placeholder="Rechercher..." class="px-4 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500 text-base">

<i class="fas fa-search absolute right-3 top-3 text-


gray-400"></i>

</div>

<select id="filter-employe-non-titulaire" class="px-4 py-


2 rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500 text-base">

<option value="all">Tous les statuts</option>

<option value="en-attente">En attente</option>

<option value="confirme">Confirmé</option>

<option value="rejete">Rejeté</option>

</select>
</div>

</div>

<!-- Client Cards -->

<div id="employe-non-titulaire-list" class="grid grid-cols-1


md:grid-cols-2 xl:grid-cols-3 gap-4">

<div class="card-bg rounded-lg shadow p-4 col-span-full


text-center">

<div class="loading-spinner mx-auto mb-4"></div>

<p class="text-lg">Chargement des clients...</p>

</div>

</div>

</section>

<!-- Profession Libérale avec ID Fiscale Section -->

<section id="profession-lib-fisc" class="hidden">

<div class="flex justify-between items-center mb-6">

<h1 class="text-2xl font-bold">Profession Libérale avec ID


Fiscale</h1>

<div class="flex space-x-2">

<div class="relative">

<input type="text" id="search-profession-lib-fisc"


placeholder="Rechercher..." class="px-4 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500 text-base">

<i class="fas fa-search absolute right-3 top-3 text-


gray-400"></i>

</div>
<select id="filter-profession-lib-fisc" class="px-4 py-2
rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500 text-base">

<option value="all">Tous les statuts</option>

<option value="en-attente">En attente</option>

<option value="confirme">Confirmé</option>

<option value="rejete">Rejeté</option>

</select>

</div>

</div>

<!-- Client Cards -->

<div id="profession-lib-fisc-list" class="grid grid-cols-1


md:grid-cols-2 xl:grid-cols-3 gap-4">

<div class="card-bg rounded-lg shadow p-4 col-span-full


text-center">

<div class="loading-spinner mx-auto mb-4"></div>

<p class="text-lg">Chargement des clients...</p>

</div>

</div>

</section>

<!-- Profession Libérale sans ID Fiscale Section -->

<section id="profession-lib-non-fisc" class="hidden">

<div class="flex justify-between items-center mb-6">

<h1 class="text-2xl font-bold">Profession Libérale sans ID


Fiscale</h1>

<div class="flex space-x-2">


<div class="relative">

<input type="text" id="search-profession-lib-non-fisc"


placeholder="Rechercher..." class="px-4 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500 text-base">

<i class="fas fa-search absolute right-3 top-3 text-


gray-400"></i>

</div>

<select id="filter-profession-lib-non-fisc" class="px-4 py-


2 rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500 text-base">

<option value="all">Tous les statuts</option>

<option value="en-attente">En attente</option>

<option value="confirme">Confirmé</option>

<option value="rejete">Rejeté</option>

</select>

</div>

</div>

<!-- Client Cards -->

<div id="profession-lib-non-fisc-list" class="grid grid-cols-1


md:grid-cols-2 xl:grid-cols-3 gap-4">

<div class="card-bg rounded-lg shadow p-4 col-span-full


text-center">

<div class="loading-spinner mx-auto mb-4"></div>

<p class="text-lg">Chargement des clients...</p>

</div>

</div>

</section>
<!-- Chomeur Section -->

<section id="chomeur" class="hidden">

<div class="flex justify-between items-center mb-6">

<h1 class="text-2xl font-bold">Chomeur</h1>

<div class="flex space-x-2">

<div class="relative">

<input type="text" id="search-chomeur"


placeholder="Rechercher..." class="px-4 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500 text-base">

<i class="fas fa-search absolute right-3 top-3 text-


gray-400"></i>

</div>

<select id="filter-chomeur" class="px-4 py-2 rounded-lg


border shadow-sm focus:outline-none focus:ring-2 focus:ring-green-500 text-
base">

<option value="all">Tous les statuts</option>

<option value="en-attente">En attente</option>

<option value="confirme">Confirmé</option>

<option value="rejete">Rejeté</option>

</select>

</div>

</div>

<!-- Client Cards -->

<div id="chomeur-list" class="grid grid-cols-1 md:grid-cols-2


xl:grid-cols-3 gap-4">

<div class="card-bg rounded-lg shadow p-4 col-span-full


text-center">

<div class="loading-spinner mx-auto mb-4"></div>


<p class="text-lg">Chargement des clients...</p>

</div>

</div>

</section>

<!-- Résident à l'étranger Section -->

<section id="resident-etranger" class="hidden">

<div class="flex justify-between items-center mb-6">

<h1 class="text-2xl font-bold">Tunisien Résident à


l'étranger</h1>

<div class="flex space-x-2">

<div class="relative">

<input type="text" id="search-resident-etranger"


placeholder="Rechercher..." class="px-4 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500 text-base">

<i class="fas fa-search absolute right-3 top-3 text-


gray-400"></i>

</div>

<select id="filter-resident-etranger" class="px-4 py-2


rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500 text-base">

<option value="all">Tous les statuts</option>

<option value="en-attente">En attente</option>

<option value="confirme">Confirmé</option>

<option value="rejete">Rejeté</option>

</select>

</div>

</div>
<!-- Client Cards -->

<div id="resident-etranger-list" class="grid grid-cols-1


md:grid-cols-2 xl:grid-cols-3 gap-4">

<div class="card-bg rounded-lg shadow p-4 col-span-full


text-center">

<div class="loading-spinner mx-auto mb-4"></div>

<p class="text-lg">Chargement des clients...</p>

</div>

</div>

</section>

<!-- Déclaration de Problèmes Section -->

<section id="problemes" class="hidden">

<h1 class="text-2xl font-bold mb-6">Déclaration de


Problèmes</h1>

<!-- Submit Problem Form -->

<div class="card-bg rounded-lg shadow p-4 mb-6">

<h2 class="text-lg font-semibold mb-4">Soumettre un


problème</h2>

<form id="problem-form" class="space-y-4">

<div>

<label for="problem-title" class="block mb-1 font-


medium">Titre</label>

<input type="text" id="problem-title"


placeholder="Titre du problème" class="w-full px-4 py-2 rounded-lg border
shadow-sm focus:outline-none focus:ring-2 focus:ring-green-500">

</div>

<div>
<label for="problem-description" class="block mb-1
font-medium">Description</label>

<textarea id="problem-description" rows="4"


placeholder="Décrivez le problème en détail" class="w-full px-4 py-2
rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500"></textarea>

</div>

<div>

<label for="problem-priority" class="block mb-1 font-


medium">Priorité</label>

<select id="problem-priority" class="w-full px-4 py-2


rounded-lg border shadow-sm focus:outline-none focus:ring-2 focus:ring-
green-500">

<option value="low">Basse</option>

<option value="medium"
selected>Moyenne</option>

<option value="high">Haute</option>

<option value="critical">Critique</option>

</select>

</div>

<button type="submit" class="btn-primary px-6 py-2


rounded-lg">Soumettre</button>

</form>

</div>

<!-- Problem History -->

<div class="card-bg rounded-lg shadow p-4">

<h2 class="text-lg font-semibold mb-4">Historique des


problèmes</h2>

<div class="overflow-x-auto">
<table class="data-table">

<thead>

<tr>

<th>Date</th>

<th>Titre</th>

<th>Priorité</th>

<th>Statut</th>

<th>Actions</th>

</tr>

</thead>

<tbody id="problems-list">

<tr id="no-problems-message">

<td colspan="5" class="text-center py-


4">Aucun problème signalé</td>

</tr>

</tbody>

</table>

</div>

</div>

</section>

</div>

</div>

</div>

</div>

<!-- Notifications Modal -->

<div id="notifications-modal" class="modal">


<div class="modal-content">

<span class="close-modal" id="close-notifications">&times;</span>

<h2 class="text-xl font-bold mb-4">Notifications</h2>

<div id="notifications-list" class="space-y-4 max-h-96 overflow-y-


auto">

<div class="text-center py-4">

<p>Aucune notification disponible</p>

</div>

</div>

</div>

</div>

<!-- Client Info Modal -->

<div id="client-info-modal" class="modal">

<div class="modal-content">

<span class="close-modal" id="close-client-info">&times;</span>

<h2 class="text-xl font-bold mb-4">Informations du client</h2>

<div id="client-info-content" class="space-y-3 max-h-96 overflow-y-


auto">

<div class="text-center py-4">

<div class="loading-spinner mx-auto mb-4"></div>

<p>Chargement des informations...</p>

</div>

</div>

</div>

</div>
<!-- Call Tracking Modal -->

<div id="call-tracking-modal" class="modal">

<div class="modal-content">

<span class="close-modal" id="close-call-tracking">&times;</span>

<h2 class="text-xl font-bold mb-4">Suivi des appels</h2>

<div id="call-tracking-content">

<div class="space-y-4 mb-6">

<div id="call-1-info" class="card-bg rounded-lg p-3 border-l-4


border-green-500">

<h3 class="font-semibold">Premier appel</h3>

<p class="text-sm mb-2"><span id="call-1-date">Date


programmée</span></p>

<div class="flex space-x-2">

<button id="complete-call-1" class="bg-green-500 text-


white px-3 py-1 rounded text-sm">Complété</button>

<button id="miss-call-1" class="bg-red-500 text-white px-3


py-1 rounded text-sm">Manqué</button>

</div>

</div>

<div id="call-2-info" class="card-bg rounded-lg p-3 border-l-4


border-yellow-500">

<h3 class="font-semibold">Deuxième appel</h3>

<p class="text-sm mb-2"><span id="call-2-date">Date


programmée</span></p>

<div class="flex space-x-2">

<button id="complete-call-2" class="bg-green-500 text-


white px-3 py-1 rounded text-sm">Complété</button>
<button id="miss-call-2" class="bg-red-500 text-white px-3
py-1 rounded text-sm">Manqué</button>

</div>

</div>

<div id="call-3-info" class="card-bg rounded-lg p-3 border-l-4


border-blue-500">

<h3 class="font-semibold">Troisième appel</h3>

<p class="text-sm mb-2"><span id="call-3-date">Date


programmée</span></p>

<div class="flex space-x-2">

<button id="complete-call-3" class="bg-green-500 text-


white px-3 py-1 rounded text-sm">Complété</button>

<button id="miss-call-3" class="bg-red-500 text-white px-3


py-1 rounded text-sm">Manqué</button>

</div>

</div>

</div>

<div class="card-bg rounded-lg p-3">

<h3 class="font-semibold mb-2">Notes d'appel</h3>

<textarea id="call-notes" rows="4" placeholder="Ajouter des


notes sur l'appel..." class="w-full px-3 py-2 rounded-lg border shadow-sm
focus:outline-none focus:ring-2 focus:ring-green-500"></textarea>

<button id="save-call-notes" class="bg-green-500 text-white


px-4 py-2 rounded mt-2">Sauvegarder</button>

</div>

</div>

</div>
</div>

<!-- Client Status Modal -->

<div id="client-status-modal" class="modal">

<div class="modal-content">

<span class="close-modal" id="close-client-status">&times;</span>

<h2 class="text-xl font-bold mb-4">Changer le statut du client</h2>

<div class="space-y-4">

<p class="text-center font-medium">Client: <span id="status-


client-name"></span></p>

<div class="flex flex-col space-y-2">

<label class="flex items-center space-x-2 p-2 rounded hover:bg-


gray-100 cursor-pointer">

<input type="radio" name="client-status" value="en-


attente" class="h-4 w-4">

<span>En attente</span>

</label>

<label class="flex items-center space-x-2 p-2 rounded hover:bg-


gray-100 cursor-pointer">

<input type="radio" name="client-status" value="confirme"


class="h-4 w-4">

<span>Confirmé</span>

</label>

<label class="flex items-center space-x-2 p-2 rounded hover:bg-


gray-100 cursor-pointer">

<input type="radio" name="client-status" value="rejete"


class="h-4 w-4">

<span>Rejeté</span>
</label>

</div>

<div>

<label for="status-notes" class="block mb-1 font-


medium">Notes</label>

<textarea id="status-notes" rows="3" placeholder="Ajouter des


notes sur ce changement de statut..." class="w-full px-3 py-2 rounded-lg
border shadow-sm focus:outline-none focus:ring-2
focus:ring-green-500"></textarea>

</div>

<div class="flex justify-end space-x-2">

<button id="cancel-status-change" class="bg-gray-300 text-


gray-700 px-4 py-2 rounded">Annuler</button>

<button id="save-status-change" class="bg-green-500 text-


white px-4 py-2 rounded">Sauvegarder</button>

</div>

</div>

</div>

</div>

<script>

// Main application code

document.addEventListener('DOMContentLoaded', function() {

// ------------------------

// Global variables

// ------------------------

let allClients = [];


let currentClientId = null;

let problems = JSON.parse(localStorage.getItem('problems') || '[]');

let notifications = JSON.parse(localStorage.getItem('notifications') ||


'[]');

// ------------------------

// Mock data for demonstration

// ------------------------

// Function to generate random data (will be replaced with actual


data)

function generateMockData() {

const clientTypes = [

"Employé titulaire - ‫"موظف مرسم‬,

"Employé non titulaire - ‫"موظف غير مرسم‬,

"Profession libérale disposant didentification fiscale - ‫تشتغل‬


)‫"لحسابك الخاص و لديك معرف جبائي (باتيندة‬,

"Profession libérale non disposant didentification fiscale - ‫تشتغل‬


)‫"لحسابك الخاص و ليس لديك معرف جبائي (باتيندة‬,

"Chomeur - ‫"عاطل عن العمل‬

];

const statuses = ['en-attente', 'confirme', 'rejete'];

const statusWeights = [0.6, 0.3, 0.1]; // 60% pending, 30%


confirmed, 10% rejected

const callStatuses = ['pending', 'scheduled', 'completed', 'missed'];

const callStatusWeights = [0.2, 0.3, 0.4, 0.1];


const loanTypes = [

" ‫ قرض استهالكي‬- Consumer loan",

"‫ قرض بعث مشروع‬- Project loan",

" ‫ قرض سيارة‬- Car loan",

" ‫ قرض صغير‬- micro-credit",

"‫ قرض عقاري‬- Mortgage loan"

];

// Parse data from the CSV

const csvData = `Timestamp,Column 1, ‫اإلسم و اللقب‬,‫ هل انت موافق ؟‬-


Nom et Prénom,‫_الجنس‬Genre,‫العمر‬-âge,‫ رقم الهاتف‬- Numéro de téléphone, ‫هل‬
‫ أنت مقيم بالخارج؟‬- es-tu résidant à l'étranger?,‫ الوالية‬- gouvernorat, ‫العنوان و الرقم‬
‫ البريدي‬- Adresse et code postal,‫ بلد االقامة‬- Pays de résidence,‫ هل لديك عقد عمل؟‬-
Disposez-vous un contrat de travail?, ‫ هل لديك فكرة مشروع؟‬- Avez-vous une
idée de projet ?, ‫هل انت مهتم بالمشاركة بدورة تكوينية‬,‫هل لديك دراسة مشروع جاهزة؟‬
‫المهنة‬, ‫ للتاطير والمساعدة في الحصول على قرض بعث مشروع؟‬- Profession , ‫األجرالصافي‬
‫ أو المدخول الشهري‬- Salaire net ou revenue mensuel, ‫هل عندك اقتطاع على األجر‬
‫ حاليا؟‬- Avez-vous des cessions sur salaire?, ‫ هل عندك اقتطاع على األجر حاليا؟‬- Avez-
vous des cessions sur salaire?, ‫ طريقة الحصول على األجر‬- Moyen d'obtention de
salaire, ‫ مدة الحصول على المعرف جبائي (باتيندة) بالشهر‬- Ancienneté de la patente
en mois,‫ نوع عقد العمل‬- Type de contrat,‫ نوع القرض المطلوب‬- Type du crédit
demandé, ‫األجرالصافي أو المدخول الشهري بالدينار التونسي‬- Salaire net ou revenue
mensuel en Dinars Tunisien, ‫مبلغ القرض المطلوب بالدينار التونسي‬- Montant du
crédit demandé en Dinars Tunisien, ‫ نوع القرض المطلوب‬- Type du crédit
demandé,‫ مبلغ القرض المطلوب‬- Montant du crédit demandé, ‫ هل عندك قرض حاليا؟‬-
Avez vous un crédit en cours?,‫ نوع القرض المتحصل عليه‬- Type du crédit obtenu,
‫ قيمة القرض المتحصل عليه‬- Montant du crédit obtenu, ‫هل تجاوزت نصف مدة خالص‬
‫ القرض المتحصل عليه‬- Avez-vous dépassé la moitié de la période totale de
remboursement,‫ كم عمرك ؟‬- Quel est votre âge ?`;

const csvRows = [];

// Create array of clients from the CSV data we have


const lines = parseCsvData();

const numRows = lines.length > 1 ? lines.length - 1 : 0;

for (let i = 1; i <= 200; i++) {

// Choose random line from parsed data when available

const randomLineIndex = numRows > 0 ?


Math.floor(Math.random() * numRows) + 1 : 0;

const randomLine = numRows > 0 ? lines[randomLineIndex] : [];

// Pick random client type or use from data if available

const typeIndex = Math.floor(Math.random() *


clientTypes.length);

const clientType = randomLine[15] ? randomLine[15] :


clientTypes[typeIndex];

// Pick status based on weighted random selection

const statusIndex = weightedRandomIndex(statusWeights);

const status = statuses[statusIndex];

// Generate random dates

const submissionDate = randomDateInRange(new Date(2024, 1,


1), new Date());

// Generate client info

const client = {

id: i,

timestamp: submissionDate.toISOString(),

name: randomLine[3] ? randomLine[3] : `Client ${i}`,


phone: randomLine[6] ? randomLine[6] : `+216$
{Math.floor(Math.random() * 90000000) + 10000000}`,

gender: Math.random() > 0.5 ? 'Male' : 'Female',

age: Math.floor(Math.random() * 40) + 25,

profession: clientType,

salary: randomLine[16] ? randomLine[16] :


Math.floor(Math.random() * 3000) + 500,

address: randomLine[9] ? randomLine[9] : 'Tunis, Tunisia',

loanType: randomLine[21] ? randomLine[21] :


loanTypes[Math.floor(Math.random() * loanTypes.length)],

loanAmount: randomLine[25] ? randomLine[25] :


Math.floor(Math.random() * 50000) + 5000,

hasExistingLoan: Math.random() > 0.7,

existingLoanType: '',

existingLoanAmount: 0,

status: status,

statusNotes: '',

resident_etranger: randomLine[7] ? randomLine[7] === 'oui-


‫ 'نعم‬: Math.random() > 0.9,

residence_country: randomLine[10] ? randomLine[10] :


(Math.random() > 0.9 ? 'France' : 'Tunisia'),

calls: {

first: {

date: submissionDate,

status: weightedRandomStatus(callStatuses,
callStatusWeights),

notes: ''

},

second: {
date: new Date(submissionDate.getTime() + 2 * 24 * 60
* 60 * 1000),

status: weightedRandomStatus(callStatuses,
callStatusWeights),

notes: ''

},

third: {

date: new Date(submissionDate.getTime() + 7 * 24 * 60


* 60 * 1000),

status: weightedRandomStatus(callStatuses,
callStatusWeights),

notes: ''

};

// Add existing loan info for some clients

if (client.hasExistingLoan) {

client.existingLoanType = randomLine[27] ? randomLine[27] :


loanTypes[Math.floor(Math.random() * loanTypes.length)];

client.existingLoanAmount = randomLine[28] ?
randomLine[28] : Math.floor(Math.random() * 30000) + 1000;

// Generate full client data from CSV rows if available

if (randomLine.length > 0) {

// Add more mapped fields if needed

}
csvRows.push(client);

return csvRows;

// Helper function for weighted random selection

function weightedRandomIndex(weights) {

const sum = weights.reduce((acc, val) => acc + val, 0);

let random = Math.random() * sum;

for (let i = 0; i < weights.length; i++) {

random -= weights[i];

if (random < 0) {

return i;

return weights.length - 1;

function weightedRandomStatus(statuses, weights) {

const index = weightedRandomIndex(weights);

return statuses[index];

function randomDateInRange(start, end) {


return new Date(start.getTime() + Math.random() * (end.getTime()
- start.getTime()));

// Parse the CSV data from the provided input

function parseCsvData() {

// Get the CSV data from the attached document

const csvContent = `Timestamp,Column 1, ‫اإلسم و‬,‫هل انت موافق ؟‬


‫ اللقب‬- Nom et Prénom,‫_الجنس‬Genre,‫العمر‬-âge,‫ رقم الهاتف‬- Numéro de
téléphone,‫ هل أنت مقيم بالخارج؟‬- es-tu résidant à l'étranger?,‫ الوالية‬-
gouvernorat, ‫ العنوان و الرقم البريدي‬- Adresse et code postal,‫ بلد االقامة‬- Pays de
résidence,‫ هل لديك عقد عمل؟‬- Disposez-vous un contrat de travail?, ‫هل لديك فكرة‬
‫ مشروع؟‬- Avez-vous une idée de projet ?,‫هل انت مهتم‬,‫هل لديك دراسة مشروع جاهزة؟‬
‫المهنة‬, ‫ بالمشاركة بدورة تكوينية للتاطير والمساعدة في الحصول على قرض بعث مشروع؟‬-
Profession , ‫ األجرالصافي أو المدخول الشهري‬- Salaire net ou revenue mensuel, ‫هل‬
‫ عندك اقتطاع على األجر حاليا؟‬- Avez-vous des cessions sur salaire?, ‫هل عندك اقتطاع‬
‫ على األجر حاليا؟‬- Avez-vous des cessions sur salaire?, ‫ طريقة الحصول على األجر‬-
Moyen d'obtention de salaire, ‫ مدة الحصول على المعرف جبائي (باتيندة) بالشهر‬-
Ancienneté de la patente en mois, ‫ نوع عقد العمل‬- Type de contrat, ‫نوع القرض‬
‫ المطلوب‬- Type du crédit demandé, ‫األجرالصافي أو المدخول الشهري بالدينار التونسي‬-
Salaire net ou revenue mensuel en Dinars Tunisien, ‫مبلغ القرض المطلوب بالدينار‬
‫التونسي‬- Montant du crédit demandé en Dinars Tunisien, ‫ نوع القرض المطلوب‬-
Type du crédit demandé,‫ مبلغ القرض المطلوب‬- Montant du crédit demandé, ‫هل‬
‫ عندك قرض حاليا؟‬- Avez vous un crédit en cours?, ‫ نوع القرض المتحصل عليه‬- Type
du crédit obtenu,‫ قيمة القرض المتحصل عليه‬- Montant du crédit obtenu, ‫هل تجاوزت‬
‫ نصف مدة خالص القرض المتحصل عليه‬- Avez-vous dépassé la moitié de la période
totale de remboursement,‫ كم عمرك ؟‬- Quel est votre âge ?

2024-02-15 15:48:42.637000,,,sirine smida,,,52622489.0,,,,,,,,,,,,,,,, ‫قرض‬


‫استهالكي‬,,,,,,,,,

2024-02-17 14:03:55.098000,,,Amdouni youssef,,,54208031.0,,,,,,,,,,,,,,,, ‫قرض‬


‫ صغير‬micro-credit,,,,,,,,,

2024-02-17 14:09:13.223000,,,‫قرض صغير‬,,,,,,,,,,,,,,,,54208031.0,,,‫يوسف العمدوني‬


micro-credit,,,,,,,,,`;
// Split into lines

const lines = csvContent.split('\n');

// Convert each line to an array of values (simple split by comma)

// This is a simplified approach - proper CSV parsing would handle


quotes and escaped characters

return lines.map(line => line.split(','));

// ------------------------

// Utility functions

// ------------------------

// Format date for display

function formatDate(dateString) {

const date = new Date(dateString);

return date.toLocaleDateString('fr-FR', {

year: 'numeric',

month: 'short',

day: 'numeric',

hour: '2-digit',

minute: '2-digit'

});

// Function to show only a specific section

function showSection(sectionId) {

// Hide all sections


document.querySelectorAll('#content-area >
section').forEach(section => {

section.classList.add('hidden');

});

// Show the requested section

const sectionToShow = document.getElementById(sectionId);

if (sectionToShow) {

sectionToShow.classList.remove('hidden');

// Update active state in navigation

document.querySelectorAll('.nav-link').forEach(link => {

link.classList.remove('bg-green-500', 'text-white');

link.classList.add('hover:bg-gray-100', 'dark:hover:bg-gray-
700');

});

const activeLink = document.querySelector(`.nav-link[href="#$


{sectionId}"]`);

if (activeLink) {

activeLink.classList.add('bg-green-500', 'text-white');

activeLink.classList.remove('hover:bg-gray-100',
'dark:hover:bg-gray-700');

// Open modal function


function openModal(modalId) {

const modal = document.getElementById(modalId);

if (modal) {

modal.style.display = 'block';

// Close modal function

function closeModal(modalId) {

const modal = document.getElementById(modalId);

if (modal) {

modal.style.display = 'none';

// Filter clients based on search term and status

function filterClients(clients, searchTerm, statusFilter) {

return clients.filter(client => {

// Search term filtering

const matchesSearch = !searchTerm ||

client.name.toLowerCase().includes(searchTerm.toLowerCase()) ||

client.phone.toLowerCase().includes(searchTerm.toLowerCase());

// Status filtering

const matchesStatus = statusFilter === 'all' || client.status


=== statusFilter;
return matchesSearch && matchesStatus;

});

// Generate client card HTML

function generateClientCard(client) {

// Define status badge class

let statusBadgeClass = '';

let statusLabel = '';

switch(client.status) {

case 'en-attente':

statusBadgeClass = 'status-pending';

statusLabel = 'En attente';

break;

case 'confirme':

statusBadgeClass = 'status-confirmed';

statusLabel = 'Confirmé';

break;

case 'rejete':

statusBadgeClass = 'status-rejected';

statusLabel = 'Rejeté';

break;

// Create call badges


const callBadges = generateCallBadges(client);

return `

<div class="client-card card-bg rounded-lg shadow p-4" data-


client-id="${client.id}">

<div class="flex justify-between items-start mb-3">

<h3 class="font-bold">${client.name}</h3>

<span class="status-badge ${statusBadgeClass}">$


{statusLabel}</span>

</div>

<div class="space-y-2 mb-3">

<p class="flex items-center text-sm">

<i class="fas fa-phone mr-2 text-gray-500"></i>

${client.phone}

</p>

<p class="flex items-center text-sm">

<i class="fas fa-calendar-alt mr-2 text-gray-500"></i>

${formatDate(client.timestamp)}

</p>

<p class="flex items-center text-sm">

<i class="fas fa-money-bill-wave mr-2 text-gray-500"></i>

${client.loanType}

</p>

</div>

<div class="flex items-center mb-3">

<div class="text-sm text-gray-500 mr-2">Suivi des


appels:</div>

${callBadges}
</div>

<div class="flex justify-between mt-2">

<div class="space-x-1">

<button class="track-calls-btn bg-blue-500 text-white px-3


py-1 rounded text-sm" data-client-id="${client.id}">

<i class="fas fa-phone-alt mr-1"></i> Appels

</button>

<button class="client-info-btn bg-gray-500 text-white px-3


py-1 rounded text-sm" data-client-id="${client.id}">

<i class="fas fa-info-circle mr-1"></i> Info

</button>

</div>

<button class="change-status-btn bg-green-500 text-white


px-3 py-1 rounded text-sm" data-client-id="${client.id}">

<i class="fas fa-exchange-alt mr-1"></i> Statut

</button>

</div>

</div>

`;

// Generate call tracking badges

function generateCallBadges(client) {

let badges = '';

const callStatuses = [

{ number: 1, status: client.calls.first.status },

{ number: 2, status: client.calls.second.status },


{ number: 3, status: client.calls.third.status }

];

callStatuses.forEach(call => {

let badgeClass = '';

switch(call.status) {

case 'pending':

badgeClass = 'call-pending';

break;

case 'scheduled':

badgeClass = 'call-scheduled';

break;

case 'completed':

badgeClass = 'call-completed';

break;

case 'missed':

badgeClass = 'call-missed';

break;

badges += `<span class="call-badge ${badgeClass}">$


{call.number}</span>`;

});

return badges;

}
// Display client details in the modal

function displayClientInfo(clientId) {

const client = allClients.find(c => c.id === parseInt(clientId));

if (!client) {

return;

let infoHtml = `

<div class="space-y-3">

<div class="flex justify-between items-center border-b pb-2">

<h3 class="text-lg font-bold">${client.name}</h3>

<span class="text-sm text-gray-500">#${client.id}</span>

</div>

<div class="grid grid-cols-2 gap-4">

<div>

<p class="text-sm text-gray-500">Téléphone</p>

<p>${client.phone}</p>

</div>

<div>

<p class="text-sm text-gray-500">Date de


soumission</p>

<p>${formatDate(client.timestamp)}</p>

</div>

<div>
<p class="text-sm text-gray-500">Profession</p>

<p>${client.profession}</p>

</div>

<div>

<p class="text-sm text-gray-500">Salaire mensuel</p>

<p>${client.salary} DT</p>

</div>

<div>

<p class="text-sm text-gray-500">Type de prêt


demandé</p>

<p>${client.loanType}</p>

</div>

<div>

<p class="text-sm text-gray-500">Montant demandé</p>

<p>${client.loanAmount} DT</p>

</div>

</div>

<div class="border-t pt-2">

<p class="text-sm text-gray-500">Adresse</p>

<p>${client.address || 'Non spécifié'}</p>

</div>

<div class="border-t pt-2">

<p class="text-sm text-gray-500">Statut actuel</p>

<p class="font-medium">${

client.status === 'en-attente' ? 'En attente' :


client.status === 'confirme' ? 'Confirmé' :

client.status === 'rejete' ? 'Rejeté' : 'Non défini'

}</p>

${client.statusNotes ? `<p class="text-sm mt-1 italic">"$


{client.statusNotes}"</p>` : ''}

</div>

<div class="border-t pt-2">

<p class="text-sm text-gray-500">Prêt existant</p>

<p>${client.hasExistingLoan ? 'Oui' : 'Non'}</p>

${client.hasExistingLoan ? `

<div class="grid grid-cols-2 gap-4 mt-2">

<div>

<p class="text-sm text-gray-500">Type</p>

<p>${client.existingLoanType}</p>

</div>

<div>

<p class="text-sm text-gray-500">Montant</p>

<p>${client.existingLoanAmount} DT</p>

</div>

</div>` : ''}

</div>

<div class="border-t pt-2">

<p class="text-sm text-gray-500">Résident à l'étranger</p>

<p>${client.resident_etranger ? 'Oui' : 'Non'}</p>

${client.resident_etranger ? `
<div class="mt-2">

<p class="text-sm text-gray-500">Pays de résidence</p>

<p>${client.residence_country || 'Non spécifié'}</p>

</div>` : ''}

</div>

</div>

`;

document.getElementById('client-info-content').innerHTML =
infoHtml;

// ------------------------

// Dashboard functionality

// ------------------------

// Initialize charts

function initializeCharts() {

// Monthly Submissions Chart

const submissionsCtx = document.getElementById('submissions-


chart').getContext('2d');

const submissionsChart = new Chart(submissionsCtx, {

type: 'line',

data: {

labels: ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aoû', 'Sep',
'Oct', 'Nov', 'Déc'],

datasets: [{

label: 'Soumissions',
data: [12, 19, 30, 45, 56, 68, 71, 84, 90, 102, 110, 125],

backgroundColor: 'rgba(76, 175, 80, 0.2)',

borderColor: 'rgba(76, 175, 80, 1)',

borderWidth: 2,

tension: 0.3

}]

},

options: {

responsive: true,

maintainAspectRatio: false,

scales: {

y: {

beginAtZero: true,

precision: 0

},

plugins: {

legend: {

display: false

});

// Client Types Chart

const clientTypesCtx = document.getElementById('client-types-


chart').getContext('2d');
const clientTypesChart = new Chart(clientTypesCtx, {

type: 'doughnut',

data: {

labels: [

'Employé titulaire',

'Employé non titulaire',

'Profession libérale avec IF',

'Profession libérale sans IF',

'Chomeur',

'Résident à l\'étranger'

],

datasets: [{

data: [35, 25, 15, 10, 10, 5],

backgroundColor: [

'rgba(76, 175, 80, 0.7)',

'rgba(33, 150, 243, 0.7)',

'rgba(255, 193, 7, 0.7)',

'rgba(156, 39, 176, 0.7)',

'rgba(244, 67, 54, 0.7)',

'rgba(96, 125, 139, 0.7)'

],

borderWidth: 1

}]

},

options: {

responsive: true,

maintainAspectRatio: false,
plugins: {

legend: {

position: 'right',

labels: {

padding: 15,

usePointStyle: true,

pointStyle: 'circle'

});

// Confirmed Clients Chart

const confirmedCtx = document.getElementById('confirmed-


chart').getContext('2d');

const confirmedChart = new Chart(confirmedCtx, {

type: 'bar',

data: {

labels: ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aoû', 'Sep',
'Oct', 'Nov', 'Déc'],

datasets: [{

label: 'Clients Confirmés',

data: [5, 8, 12, 18, 23, 28, 33, 38, 42, 46, 50, 55],

backgroundColor: 'rgba(76, 175, 80, 0.7)',

borderColor: 'rgba(76, 175, 80, 1)',

borderWidth: 1
}]

},

options: {

responsive: true,

maintainAspectRatio: false,

scales: {

y: {

beginAtZero: true,

precision: 0

},

plugins: {

legend: {

display: false

});

// Client Status Chart

const statusCtx = document.getElementById('client-status-


chart').getContext('2d');

const statusChart = new Chart(statusCtx, {

type: 'pie',

data: {

labels: ['En attente', 'Confirmé', 'Rejeté'],

datasets: [{
data: [65, 25, 10],

backgroundColor: [

'rgba(255, 193, 7, 0.7)',

'rgba(76, 175, 80, 0.7)',

'rgba(244, 67, 54, 0.7)'

],

borderWidth: 1

}]

},

options: {

responsive: true,

maintainAspectRatio: false,

plugins: {

legend: {

position: 'right',

labels: {

padding: 15,

usePointStyle: true,

pointStyle: 'circle'

});

// Event listeners for chart buttons


document.getElementById('monthly-chart-
btn').addEventListener('click', function() {

this.classList.add('bg-green-500', 'text-white');

this.classList.remove('bg-gray-300', 'text-gray-700');

document.getElementById('weekly-chart-btn').classList.add('bg-
gray-300', 'text-gray-700');

document.getElementById('weekly-chart-
btn').classList.remove('bg-green-500', 'text-white');

// Update chart data for monthly view (example)

submissionsChart.data.labels = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai',


'Juin', 'Juil', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc'];

submissionsChart.data.datasets[0].data = [12, 19, 30, 45, 56,


68, 71, 84, 90, 102, 110, 125];

submissionsChart.update();

});

document.getElementById('weekly-chart-
btn').addEventListener('click', function() {

this.classList.add('bg-green-500', 'text-white');

this.classList.remove('bg-gray-300', 'text-gray-700');

document.getElementById('monthly-chart-
btn').classList.add('bg-gray-300', 'text-gray-700');

document.getElementById('monthly-chart-
btn').classList.remove('bg-green-500', 'text-white');

// Update chart data for weekly view (example)

submissionsChart.data.labels = ['Semaine 1', 'Semaine 2',


'Semaine 3', 'Semaine 4'];

submissionsChart.data.datasets[0].data = [28, 35, 42, 38];


submissionsChart.update();

});

document.getElementById('monthly-confirmed-
btn').addEventListener('click', function() {

this.classList.add('bg-green-500', 'text-white');

this.classList.remove('bg-gray-300', 'text-gray-700');

document.getElementById('daily-confirmed-
btn').classList.add('bg-gray-300', 'text-gray-700');

document.getElementById('daily-confirmed-
btn').classList.remove('bg-green-500', 'text-white');

// Update chart data for monthly view (example)

confirmedChart.data.labels = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai',


'Juin', 'Juil', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc'];

confirmedChart.data.datasets[0].data = [5, 8, 12, 18, 23, 28, 33,


38, 42, 46, 50, 55];

confirmedChart.update();

});

document.getElementById('daily-confirmed-
btn').addEventListener('click', function() {

this.classList.add('bg-green-500', 'text-white');

this.classList.remove('bg-gray-300', 'text-gray-700');

document.getElementById('monthly-confirmed-
btn').classList.add('bg-gray-300', 'text-gray-700');

document.getElementById('monthly-confirmed-
btn').classList.remove('bg-green-500', 'text-white');
// Update chart data for daily view (example)

confirmedChart.data.labels = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven',


'Sam', 'Dim'];

confirmedChart.data.datasets[0].data = [3, 4, 2, 5, 7, 3, 1];

confirmedChart.update();

});

// Update dashboard metrics with real data

function updateDashboardMetrics() {

// Calculate today's and yesterday's submissions

const today = new Date();

today.setHours(0, 0, 0, 0);

const yesterday = new Date(today);

yesterday.setDate(yesterday.getDate() - 1);

const todaysSubmissions = allClients.filter(client => {

const submissionDate = new Date(client.timestamp);

submissionDate.setHours(0, 0, 0, 0);

return submissionDate.getTime() === today.getTime();

}).length;

const yesterdaysSubmissions = allClients.filter(client => {

const submissionDate = new Date(client.timestamp);

submissionDate.setHours(0, 0, 0, 0);

return submissionDate.getTime() === yesterday.getTime();


}).length;

// Calculate this month's and last month's submissions

const currentMonth = today.getMonth();

const currentYear = today.getFullYear();

const lastMonth = currentMonth === 0 ? 11 : currentMonth - 1;

const lastMonthYear = currentMonth === 0 ? currentYear - 1 :


currentYear;

const thisMonthsSubmissions = allClients.filter(client => {

const submissionDate = new Date(client.timestamp);

return submissionDate.getMonth() === currentMonth &&


submissionDate.getFullYear() === currentYear;

}).length;

const lastMonthsSubmissions = allClients.filter(client => {

const submissionDate = new Date(client.timestamp);

return submissionDate.getMonth() === lastMonth &&


submissionDate.getFullYear() === lastMonthYear;

}).length;

// Calculate confirmed clients

const confirmedClients = allClients.filter(client => client.status


=== 'confirme');

const todaysConfirmed = confirmedClients.filter(client => {

const submissionDate = new Date(client.timestamp);


submissionDate.setHours(0, 0, 0, 0);

return submissionDate.getTime() === today.getTime();

}).length;

const yesterdaysConfirmed = confirmedClients.filter(client => {

const submissionDate = new Date(client.timestamp);

submissionDate.setHours(0, 0, 0, 0);

return submissionDate.getTime() === yesterday.getTime();

}).length;

const thisMonthsConfirmed = confirmedClients.filter(client => {

const submissionDate = new Date(client.timestamp);

return submissionDate.getMonth() === currentMonth &&


submissionDate.getFullYear() === currentYear;

}).length;

const lastMonthsConfirmed = confirmedClients.filter(client => {

const submissionDate = new Date(client.timestamp);

return submissionDate.getMonth() === lastMonth &&


submissionDate.getFullYear() === lastMonthYear;

}).length;

// Calculate percentage changes

const dailySubmissionsChange = yesterdaysSubmissions === 0 ?


100 : ((todaysSubmissions - yesterdaysSubmissions) /
yesterdaysSubmissions) * 100;

const monthlySubmissionsChange = lastMonthsSubmissions ===


0 ? 100 : ((thisMonthsSubmissions - lastMonthsSubmissions) /
lastMonthsSubmissions) * 100;
const dailyConfirmedChange = yesterdaysConfirmed === 0 ?
100 : ((todaysConfirmed - yesterdaysConfirmed) / yesterdaysConfirmed) *
100;

const monthlyConfirmedChange = lastMonthsConfirmed === 0 ?


100 : ((thisMonthsConfirmed - lastMonthsConfirmed) / lastMonthsConfirmed)
* 100;

// Update UI elements

document.getElementById('daily-submissions').textContent =
todaysSubmissions;

document.getElementById('monthly-submissions').textContent =
thisMonthsSubmissions;

document.getElementById('daily-confirmed').textContent =
todaysConfirmed;

document.getElementById('monthly-confirmed').textContent =
thisMonthsConfirmed;

// Update percentage changes

updatePercentageChange('daily-submissions-change',
dailySubmissionsChange);

updatePercentageChange('monthly-submissions-change',
monthlySubmissionsChange);

updatePercentageChange('daily-confirmed-change',
dailyConfirmedChange);

updatePercentageChange('monthly-confirmed-change',
monthlyConfirmedChange);

// Update sidebar quick stats

document.getElementById('total-clients').textContent =
allClients.length;
document.getElementById('confirmed-clients').textContent =
allClients.filter(client => client.status === 'confirme').length;

document.getElementById('pending-clients').textContent =
allClients.filter(client => client.status === 'en-attente').length;

document.getElementById('rejected-clients').textContent =
allClients.filter(client => client.status === 'rejete').length;

// Update recent activity table

updateRecentActivity();

// Update percentage change display

function updatePercentageChange(elementId, changePercentage) {

const element = document.getElementById(elementId);

const formattedPercentage = changePercentage.toFixed(1);

if (changePercentage > 0) {

element.textContent = `+${formattedPercentage}%`;

element.classList.remove('text-red-500');

element.classList.add('text-green-500');

} else {

element.textContent = `${formattedPercentage}%`;

element.classList.remove('text-green-500');

element.classList.add('text-red-500');

// Update recent activity table


function updateRecentActivity() {

// Sort clients by submission date (newest first)

const recentClients = [...allClients].sort((a, b) => new


Date(b.timestamp) - new Date(a.timestamp)).slice(0, 10);

let recentActivityHtml = '';

if (recentClients.length === 0) {

recentActivityHtml = `<tr><td colspan="6" class="text-center


py-4">Aucune activité récente</td></tr>`;

} else {

recentClients.forEach(client => {

let statusBadge = '';

switch(client.status) {

case 'en-attente':

statusBadge = '<span class="status-badge status-


pending">En attente</span>';

break;

case 'confirme':

statusBadge = '<span class="status-badge status-


confirmed">Confirmé</span>';

break;

case 'rejete':

statusBadge = '<span class="status-badge status-


rejected">Rejeté</span>';

break;

}
recentActivityHtml += `

<tr>

<td>${formatDate(client.timestamp)}</td>

<td>${client.name}</td>

<td>${client.phone}</td>

<td>${getProfessionType(client.profession)}</td>

<td>${statusBadge}</td>

<td>

<button class="client-info-btn bg-gray-500 text-white


px-3 py-1 rounded text-sm" data-client-id="${client.id}">

<i class="fas fa-info-circle"></i>

</button>

</td>

</tr>

`;

});

document.getElementById('recent-activity').innerHTML =
recentActivityHtml;

// Add event listeners to client info buttons

document.querySelectorAll('#recent-activity .client-info-
btn').forEach(button => {

button.addEventListener('click', function() {

const clientId = this.getAttribute('data-client-id');

currentClientId = clientId;
displayClientInfo(clientId);

openModal('client-info-modal');

});

});

// Get simplified profession type for display

function getProfessionType(profession) {

if (profession.includes('Employé titulaire')) {

return 'Employé titulaire';

} else if (profession.includes('Employé non titulaire')) {

return 'Employé non titulaire';

} else if (profession.includes('Profession libérale disposant')) {

return 'Prof. libérale avec IF';

} else if (profession.includes('Profession libérale non disposant')) {

return 'Prof. libérale sans IF';

} else if (profession.includes('Chomeur')) {

return 'Chomeur';

} else {

return profession;

// ------------------------

// Client list functionalities

// ------------------------
// Load clients for a specific category

function loadClientsByCategory(category, elementId) {

let filteredClients = [];

switch(category) {

case 'employe-titulaire':

filteredClients = allClients.filter(client =>


client.profession.includes('Employé titulaire'));

break;

case 'employe-non-titulaire':

filteredClients = allClients.filter(client =>


client.profession.includes('Employé non titulaire'));

break;

case 'profession-lib-fisc':

filteredClients = allClients.filter(client =>


client.profession.includes('Profession libérale disposant'));

break;

case 'profession-lib-non-fisc':

filteredClients = allClients.filter(client =>


client.profession.includes('Profession libérale non disposant'));

break;

case 'chomeur':

filteredClients = allClients.filter(client =>


client.profession.includes('Chomeur'));

break;

case 'resident-etranger':

filteredClients = allClients.filter(client =>


client.resident_etranger);

break;
}

renderClientList(filteredClients, elementId);

// Render client list

function renderClientList(clients, elementId) {

const container = document.getElementById(elementId);

if (!container) {

return;

if (clients.length === 0) {

container.innerHTML = `

<div class="card-bg rounded-lg shadow p-4 col-span-full text-


center">

<p class="text-lg">Aucun client trouvé</p>

</div>

`;

return;

let clientCardsHtml = '';

clients.forEach(client => {

clientCardsHtml += generateClientCard(client);
});

container.innerHTML = clientCardsHtml;

// Add event listeners

container.querySelectorAll('.client-info-btn').forEach(button => {

button.addEventListener('click', function() {

const clientId = this.getAttribute('data-client-id');

currentClientId = clientId;

displayClientInfo(clientId);

openModal('client-info-modal');

});

});

container.querySelectorAll('.track-calls-btn').forEach(button => {

button.addEventListener('click', function() {

const clientId = this.getAttribute('data-client-id');

currentClientId = clientId;

openCallTrackingModal(clientId);

});

});

container.querySelectorAll('.change-status-btn').forEach(button =>
{

button.addEventListener('click', function() {

const clientId = this.getAttribute('data-client-id');

currentClientId = clientId;
openStatusChangeModal(clientId);

});

});

// Set up search and filter functionality

function setupSearchAndFilter(category) {

const searchInput = document.getElementById(`search-$


{category}`);

const filterSelect = document.getElementById(`filter-$


{category}`);

if (!searchInput || !filterSelect) {

return;

// Function to apply filters and update client list

const applyFilters = () => {

const searchTerm = searchInput.value.trim();

const statusFilter = filterSelect.value;

let clients = [];

switch(category) {

case 'employe-titulaire':

clients = allClients.filter(client =>


client.profession.includes('Employé titulaire'));

break;
case 'employe-non-titulaire':

clients = allClients.filter(client =>


client.profession.includes('Employé non titulaire'));

break;

case 'profession-lib-fisc':

clients = allClients.filter(client =>


client.profession.includes('Profession libérale disposant'));

break;

case 'profession-lib-non-fisc':

clients = allClients.filter(client =>


client.profession.includes('Profession libérale non disposant'));

break;

case 'chomeur':

clients = allClients.filter(client =>


client.profession.includes('Chomeur'));

break;

case 'resident-etranger':

clients = allClients.filter(client =>


client.resident_etranger);

break;

const filteredClients = filterClients(clients, searchTerm,


statusFilter);

renderClientList(filteredClients, `${category}-list`);

};

// Set up event listeners

searchInput.addEventListener('input', applyFilters);
filterSelect.addEventListener('change', applyFilters);

// ------------------------

// Call Tracking functionality

// ------------------------

// Open call tracking modal

function openCallTrackingModal(clientId) {

const client = allClients.find(c => c.id === parseInt(clientId));

if (!client) {

return;

// Update UI with call information

document.getElementById('call-1-date').textContent =
formatDate(client.calls.first.date);

document.getElementById('call-2-date').textContent =
formatDate(client.calls.second.date);

document.getElementById('call-3-date').textContent =
formatDate(client.calls.third.date);

// Update call status UI

updateCallStatusUI(client);

// Set notes if any

document.getElementById('call-notes').value = '';
// Open the modal

openModal('call-tracking-modal');

// Update call status UI

function updateCallStatusUI(client) {

const calls = [

{ number: 1, status: client.calls.first.status, element:


document.getElementById('call-1-info') },

{ number: 2, status: client.calls.second.status, element:


document.getElementById('call-2-info') },

{ number: 3, status: client.calls.third.status, element:


document.getElementById('call-3-info') }

];

calls.forEach(call => {

// Remove all possible border classes

call.element.classList.remove('border-green-500', 'border-yellow-
500', 'border-red-500', 'border-gray-500');

// Add appropriate border color based on status

switch(call.status) {

case 'pending':

call.element.classList.add('border-gray-500');

call.element.querySelector('h3').textContent = `Appel $
{call.number} (En attente)`;

break;
case 'scheduled':

call.element.classList.add('border-yellow-500');

call.element.querySelector('h3').textContent = `Appel $
{call.number} (Programmé)`;

break;

case 'completed':

call.element.classList.add('border-green-500');

call.element.querySelector('h3').textContent = `Appel $
{call.number} (Complété)`;

break;

case 'missed':

call.element.classList.add('border-red-500');

call.element.querySelector('h3').textContent = `Appel $
{call.number} (Manqué)`;

break;

});

// Open status change modal

function openStatusChangeModal(clientId) {

const client = allClients.find(c => c.id === parseInt(clientId));

if (!client) {

return;

// Update client name


document.getElementById('status-client-name').textContent =
client.name;

// Set current status

document.querySelector(`input[name="client-status"][value="$
{client.status}"]`).checked = true;

// Set notes if any

document.getElementById('status-notes').value =
client.statusNotes || '';

// Open the modal

openModal('client-status-modal');

// ------------------------

// Problem reporting functionality

// ------------------------

// Add a problem

function addProblem(problem) {

problems.push({

id: problems.length + 1,

date: new Date().toISOString(),

title: problem.title,

description: problem.description,

priority: problem.priority,

status: 'new'
});

// Save to local storage

localStorage.setItem('problems', JSON.stringify(problems));

// Add a notification

addNotification({

type: 'problem',

title: `Nouveau problème: ${problem.title}`,

message: problem.description,

priority: problem.priority

});

// Update problems list

updateProblemsList();

// Update problems list

function updateProblemsList() {

const problemsList = document.getElementById('problems-list');

if (problems.length === 0) {

problemsList.innerHTML = `

<tr id="no-problems-message">

<td colspan="5" class="text-center py-4">Aucun problème


signalé</td>

</tr>
`;

return;

let problemsHtml = '';

problems.forEach(problem => {

let priorityBadge = '';

let statusBadge = '';

// Priority badge

switch(problem.priority) {

case 'low':

priorityBadge = '<span class="status-badge bg-blue-100


text-blue-800">Basse</span>';

break;

case 'medium':

priorityBadge = '<span class="status-badge bg-yellow-100


text-yellow-800">Moyenne</span>';

break;

case 'high':

priorityBadge = '<span class="status-badge bg-orange-


100 text-orange-800">Haute</span>';

break;

case 'critical':

priorityBadge = '<span class="status-badge bg-red-100


text-red-800">Critique</span>';

break;
}

// Status badge

switch(problem.status) {

case 'new':

statusBadge = '<span class="status-badge bg-blue-100


text-blue-800">Nouveau</span>';

break;

case 'in-progress':

statusBadge = '<span class="status-badge bg-yellow-100


text-yellow-800">En cours</span>';

break;

case 'resolved':

statusBadge = '<span class="status-badge bg-green-100


text-green-800">Résolu</span>';

break;

case 'closed':

statusBadge = '<span class="status-badge bg-gray-100


text-gray-800">Fermé</span>';

break;

problemsHtml += `

<tr>

<td>${formatDate(problem.date)}</td>

<td>

<div class="font-medium">${problem.title}</div>
<div class="text-sm text-gray-500 truncate max-w-xs">$
{problem.description}</div>

</td>

<td>${priorityBadge}</td>

<td>${statusBadge}</td>

<td>

<button class="view-problem-btn bg-blue-500 text-white


px-3 py-1 rounded text-sm mr-1" data-problem-id="${problem.id}">

<i class="fas fa-eye"></i>

</button>

<button class="delete-problem-btn bg-red-500 text-white


px-3 py-1 rounded text-sm" data-problem-id="${problem.id}">

<i class="fas fa-trash"></i>

</button>

</td>

</tr>

`;

});

problemsList.innerHTML = problemsHtml;

// Add event listeners

document.querySelectorAll('.view-problem-btn').forEach(button =>
{

button.addEventListener('click', function() {

const problemId = parseInt(this.getAttribute('data-problem-


id'));

// View problem details (to be implemented)


});

});

document.querySelectorAll('.delete-problem-btn').forEach(button
=> {

button.addEventListener('click', function() {

const problemId = parseInt(this.getAttribute('data-problem-


id'));

// Remove problem

problems = problems.filter(p => p.id !== problemId);

localStorage.setItem('problems', JSON.stringify(problems));

updateProblemsList();

});

});

// ------------------------

// Notifications functionality

// ------------------------

// Add a notification

function addNotification(notification) {

notifications.push({

id: notifications.length + 1,

date: new Date().toISOString(),

read: false,

...notification
});

// Save to local storage

localStorage.setItem('notifications', JSON.stringify(notifications));

// Update notification count

updateNotificationCount();

// Update notifications list

updateNotificationsList();

// Update notification count

function updateNotificationCount() {

const unreadCount = notifications.filter(n => !n.read).length;

const notificationBadge = document.getElementById('notification-


count');

if (unreadCount > 0) {

notificationBadge.textContent = unreadCount;

notificationBadge.classList.remove('hidden');

} else {

notificationBadge.classList.add('hidden');

// Update notifications list


function updateNotificationsList() {

const notificationsList = document.getElementById('notifications-


list');

if (notifications.length === 0) {

notificationsList.innerHTML = `

<div class="text-center py-4">

<p>Aucune notification disponible</p>

</div>

`;

return;

let notificationsHtml = '';

// Sort by date (newest first)

const sortedNotifications = [...notifications].sort((a, b) => new


Date(b.date) - new Date(a.date));

sortedNotifications.forEach(notification => {

let priorityClass = '';

if (notification.priority) {

switch(notification.priority) {

case 'low':

priorityClass = 'border-blue-500';

break;
case 'medium':

priorityClass = 'border-yellow-500';

break;

case 'high':

priorityClass = 'border-orange-500';

break;

case 'critical':

priorityClass = 'border-red-500';

break;

const readClass = notification.read ? 'opacity-60' : '';

notificationsHtml += `

<div class="notification-item card-bg rounded-lg shadow p-3


border-l-4 ${priorityClass} ${readClass}" data-notification-id="$
{notification.id}">

<div class="flex justify-between items-start">

<div>

<h3 class="font-medium">${notification.title}</h3>

<p class="text-sm">${notification.message}</p>

<p class="text-xs text-gray-500 mt-1">$


{formatDate(notification.date)}</p>

</div>

${!notification.read ? `

<button class="mark-read-btn bg-green-500 text-white px-


2 py-1 rounded-full text-xs" data-notification-id="${notification.id}">
<i class="fas fa-check"></i>

</button>

` : ''}

</div>

</div>

`;

});

notificationsList.innerHTML = notificationsHtml;

// Add event listeners

document.querySelectorAll('.mark-read-btn').forEach(button => {

button.addEventListener('click', function(e) {

e.stopPropagation();

const notificationId = parseInt(this.getAttribute('data-


notification-id'));

markNotificationAsRead(notificationId);

});

});

document.querySelectorAll('.notification-item').forEach(item => {

item.addEventListener('click', function() {

const notificationId = parseInt(this.getAttribute('data-


notification-id'));

// Mark as read

markNotificationAsRead(notificationId);
// Handle notification action if needed

const notification = notifications.find(n => n.id ===


notificationId);

if (notification && notification.type === 'problem') {

// Navigate to problems section

showSection('problemes');

closeModal('notifications-modal');

});

});

// Mark notification as read

function markNotificationAsRead(notificationId) {

notifications = notifications.map(n => {

if (n.id === notificationId) {

return { ...n, read: true };

return n;

});

// Save to local storage

localStorage.setItem('notifications', JSON.stringify(notifications));

// Update UI

updateNotificationCount();

updateNotificationsList();
}

// ------------------------

// Event listeners

// ------------------------

// Navigation links

document.querySelectorAll('.nav-link').forEach(link => {

link.addEventListener('click', function(e) {

e.preventDefault();

const targetSection = this.getAttribute('href').substring(1);

showSection(targetSection);

});

});

// Notifications button

document.getElementById('notifications-
btn').addEventListener('click', function() {

openModal('notifications-modal');

updateNotificationsList();

});

// Close notifications modal

document.getElementById('close-
notifications').addEventListener('click', function() {

closeModal('notifications-modal');

});
// Close client info modal

document.getElementById('close-client-
info').addEventListener('click', function() {

closeModal('client-info-modal');

});

// Close call tracking modal

document.getElementById('close-call-
tracking').addEventListener('click', function() {

closeModal('call-tracking-modal');

});

// Close client status modal

document.getElementById('close-client-
status').addEventListener('click', function() {

closeModal('client-status-modal');

});

// Problem form submission

document.getElementById('problem-
form').addEventListener('submit', function(e) {

e.preventDefault();

const title = document.getElementById('problem-


title').value.trim();

const description = document.getElementById('problem-


description').value.trim();
const priority = document.getElementById('problem-
priority').value;

if (!title) {

alert('Veuillez saisir un titre pour le problème');

return;

if (!description) {

alert('Veuillez saisir une description pour le problème');

return;

addProblem({

title,

description,

priority

});

// Reset form

document.getElementById('problem-title').value = '';

document.getElementById('problem-description').value = '';

document.getElementById('problem-priority').value = 'medium';

alert('Problème signalé avec succès');

});
// Call status buttons

document.getElementById('complete-call-1').addEventListener('click',
updateCallStatus.bind(null, 1, 'completed'));

document.getElementById('miss-call-1').addEventListener('click',
updateCallStatus.bind(null, 1, 'missed'));

document.getElementById('complete-call-2').addEventListener('click',
updateCallStatus.bind(null, 2, 'completed'));

document.getElementById('miss-call-2').addEventListener('click',
updateCallStatus.bind(null, 2, 'missed'));

document.getElementById('complete-call-3').addEventListener('click',
updateCallStatus.bind(null, 3, 'completed'));

document.getElementById('miss-call-3').addEventListener('click',
updateCallStatus.bind(null, 3, 'missed'));

// Update call status

function updateCallStatus(callNumber, status) {

if (!currentClientId) return;

const clientIndex = allClients.findIndex(c => c.id ===


parseInt(currentClientId));

if (clientIndex === -1) return;

const client = allClients[clientIndex];

// Update the call status

switch(callNumber) {

case 1:

client.calls.first.status = status;
break;

case 2:

client.calls.second.status = status;

break;

case 3:

client.calls.third.status = status;

break;

// Update UI

updateCallStatusUI(client);

// Save notes if any

const notes = document.getElementById('call-notes').value.trim();

if (notes) {

switch(callNumber) {

case 1:

client.calls.first.notes = notes;

break;

case 2:

client.calls.second.notes = notes;

break;

case 3:

client.calls.third.notes = notes;

break;

}
}

// Update in the array

allClients[clientIndex] = client;

// Refresh the client list

const clientType = getClientType(client);

if (clientType) {

loadClientsByCategory(clientType, `${clientType}-list`);

// Save call notes button

document.getElementById('save-call-notes').addEventListener('click',
function() {

if (!currentClientId) return;

const clientIndex = allClients.findIndex(c => c.id ===


parseInt(currentClientId));

if (clientIndex === -1) return;

const notes = document.getElementById('call-notes').value.trim();

// For simplicity, we'll just add the notes to the most recent call

const client = allClients[clientIndex];


if (client.calls.third.status !== 'pending') {

client.calls.third.notes = notes;

} else if (client.calls.second.status !== 'pending') {

client.calls.second.notes = notes;

} else {

client.calls.first.notes = notes;

// Update in the array

allClients[clientIndex] = client;

alert('Notes sauvegardées avec succès');

});

// Save status change button

document.getElementById('save-status-
change').addEventListener('click', function() {

if (!currentClientId) return;

const clientIndex = allClients.findIndex(c => c.id ===


parseInt(currentClientId));

if (clientIndex === -1) return;

const status = document.querySelector('input[name="client-


status"]:checked').value;

const notes = document.getElementById('status-


notes').value.trim();
// Update client status

allClients[clientIndex].status = status;

allClients[clientIndex].statusNotes = notes;

// Close modal

closeModal('client-status-modal');

// Refresh metrics

updateDashboardMetrics();

// Refresh the client list

const clientType = getClientType(allClients[clientIndex]);

if (clientType) {

loadClientsByCategory(clientType, `${clientType}-list`);

alert('Statut mis à jour avec succès');

});

// Cancel status change button

document.getElementById('cancel-status-
change').addEventListener('click', function() {

closeModal('client-status-modal');

});

// Get client type based on profession


function getClientType(client) {

if (client.profession.includes('Employé titulaire')) {

return 'employe-titulaire';

} else if (client.profession.includes('Employé non titulaire')) {

return 'employe-non-titulaire';

} else if (client.profession.includes('Profession libérale disposant'))


{

return 'profession-lib-fisc';

} else if (client.profession.includes('Profession libérale non


disposant')) {

return 'profession-lib-non-fisc';

} else if (client.profession.includes('Chomeur')) {

return 'chomeur';

} else if (client.resident_etranger) {

return 'resident-etranger';

return null;

// ------------------------

// Initialization

// ------------------------

// Initialize the application

function init() {

// Show loading screen


document.getElementById('loading-screen').style.display = 'flex';

// Fetch data (mocked for this example)

setTimeout(() => {

// Generate mock data

allClients = generateMockData();

// Initialize charts

initializeCharts();

// Update dashboard metrics

updateDashboardMetrics();

// Load client lists

loadClientsByCategory('employe-titulaire', 'employe-titulaire-
list');

loadClientsByCategory('employe-non-titulaire', 'employe-non-
titulaire-list');

loadClientsByCategory('profession-lib-fisc', 'profession-lib-fisc-
list');

loadClientsByCategory('profession-lib-non-fisc', 'profession-lib-
non-fisc-list');

loadClientsByCategory('chomeur', 'chomeur-list');

loadClientsByCategory('resident-etranger', 'resident-etranger-
list');

// Set up search and filter

setupSearchAndFilter('employe-titulaire');
setupSearchAndFilter('employe-non-titulaire');

setupSearchAndFilter('profession-lib-fisc');

setupSearchAndFilter('profession-lib-non-fisc');

setupSearchAndFilter('chomeur');

setupSearchAndFilter('resident-etranger');

// Update problems list

updateProblemsList();

// Update notification count

updateNotificationCount();

// Show dashboard section

showSection('dashboard');

// Hide loading screen

document.getElementById('loading-screen').style.display =
'none';

}, 2000);

// Start the application

init();

// Close modals when clicking outside

window.addEventListener('click', function(event) {

const modals = document.querySelectorAll('.modal');


modals.forEach(modal => {

if (event.target === modal) {

modal.style.display = 'none';

});

});

});

</script>

</body>

</html>

You might also like