Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 58
n/a
0 / 0
CRAP
n/a
0 / 0
1<!DOCTYPE html>
2<html lang="fr">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1">
6
7    <title><?= $title ?? 'Tableau de bord CRM' ?></title>
8
9    <meta name="description" content="Tableau de bord CRM">
10    <meta name="robots" content="noindex, nofollow">
11
12    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
13    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
14    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
15
16    <style>
17        :root {
18            --s-primary: #1a56db;
19        }
20
21        body {
22            background-color: #f4f6f9;
23            font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
24        }
25
26        /* ====================== SIDEBAR FIXE ====================== */
27        .sidebar {
28            width: 260px;
29            height: 100vh;
30            position: fixed;
31            top: 0;
32            left: 0;
33            background: #111827;
34            color: #fff;
35            padding: 20px 15px;
36            overflow-x: hidden;
37            z-index: 100;
38        }
39
40        .sidebar a {
41            color: #cbd5e1;
42            text-decoration: none;
43            display: flex;
44            align-items: center;
45            gap: 10px;
46            padding: 12px 14px;
47            border-radius: 8px;
48            white-space: nowrap;
49            transition: background 0.2s, color 0.2s;
50        }
51
52        .sidebar a:hover {
53            background: #1f2937;
54            color: #fff;
55        }
56
57        /* ====================== LOGO : conteneur fixe + image inline (plus de flicker) ====================== */
58        .logo-container {
59            height: 48px;           /* Ajustez selon la hauteur réelle de votre logo */
60            display: flex;
61            align-items: center;
62            margin-bottom: 1.5rem;
63        }
64        .logo-full {
65            max-width: 215px;
66            max-height: 100%;
67            width: auto;
68            height: auto;
69            display: block;
70        }
71        .logo-icon {
72            display: none;
73        }
74
75        /* ====================== MAIN CONTENT FIXE ====================== */
76        .content {
77            margin-left: 260px;
78            padding: 25px 30px;
79            min-height: 100vh;
80        }
81
82        /* ====================== TOPBAR ====================== */
83        .topbar {
84            background: #fff;
85            padding: 14px 24px;
86            border-radius: 14px;
87            margin-bottom: 24px;
88            box-shadow: 0 4px 14px rgba(0, 0, 0, 0.04);
89            border: 1px solid #f0f2f7;
90            display: flex;
91            justify-content: space-between;
92            align-items: center;
93        }
94
95        /* ====================== MONITOR WRAP ====================== */
96        .monitor-wrap {
97            max-width: 1800px;
98            margin: 0 auto;
99            padding: 0;
100        }
101
102        /* Scrollbar invisible */
103        .sidebar::-webkit-scrollbar { width: 0; }
104        .sidebar { scrollbar-width: none; }
105
106        /* Anti-flicker global pour les transitions */
107        body.preload-transitions-off * {
108            transition: none !important;
109        }
110    </style>
111</head>
112<body class="preload-transitions-off">
113
114<!-- SIDEBAR FIXE -->
115<div class="sidebar p-3" id="sidebar">
116    <div class="logo-container">
117        <?php
118        // Conversion du logo en base64 pour éliminer toute requête réseau et tout clignotement
119        $logoPath = FCPATH . 'assets/img/logo.png';   // Chemin absolu vers le logo
120        $logoData = '';
121        if (file_exists($logoPath)) {
122            $mime = mime_content_type($logoPath);
123            $base64 = base64_encode(file_get_contents($logoPath));
124            $logoData = 'data:' . $mime . ';base64,' . $base64;
125        } else {
126            // Fallback : URL classique (moins optimal mais conserve l'affichage)
127            $logoData = base_url('assets/img/logo.png');
128        }
129        ?>
130        <img src="<?= $logoData ?>" class="logo-full" alt="logo">
131        <img src="<?= base_url('assets/img/logo-icon.png') ?>" class="logo-icon" alt="icon">
132    </div>
133
134    <!-- DASHBOARD -->
135    <div class="menu-group mb-3">
136        <a href="<?= base_url('dashboard') ?>">
137            <i class="bi bi-speedometer2"></i><span>Tableau de bord</span>
138        </a>
139    </div>
140
141    <!-- GESTION DES ENVOIS -->
142    <div class="menu-group mb-3">
143        <div class="text-uppercase text-secondary small mb-2 px-2">Gestion des envois</div>
144
145        <a data-bs-toggle="collapse" href="#menu-envois">
146            <i class="bi bi-send"></i><span>Envois</span>
147        </a>
148        <div class="collapse ps-4 mt-1" id="menu-envois">
149            <a href="<?= base_url('dashboard/envoi/unique') ?>">Unique</a>
150            <a href="<?= base_url('dashboard/envoi/unique/brouillons') ?>">Brouillons</a>
151            <a href="<?= base_url('dashboard/envoi/unique/envoyes') ?>">Envoyés</a>
152        </div>
153
154        <a data-bs-toggle="collapse" href="#menu-masse">
155            <i class="bi bi-stack"></i><span>Masse</span>
156        </a>
157        <div class="collapse ps-4 mt-1" id="menu-masse">
158            <a href="<?= base_url('dashboard/envoi/masse') ?>">Composer</a>
159            <a href="<?= base_url('dashboard/envoi/masse/brouillons') ?>">Brouillons</a>
160            <a href="<?= base_url('dashboard/envoi/masse/envoyes') ?>">Envoyés</a>
161        </div>
162
163        <a data-bs-toggle="collapse" href="#menu-campagne">
164            <i class="bi bi-megaphone"></i><span>Campagne</span>
165        </a>
166        <div class="collapse ps-4 mt-1" id="menu-campagne">
167            <a href="<?= base_url('dashboard/campagnes/lancer') ?>">Lancer</a>
168            <a href="<?= base_url('dashboard/campagnes') ?>">Liste</a>
169            <a href="<?= base_url('dashboard/campagne/statistiques') ?>">Statistiques</a>
170        </div>
171    </div>
172
173    <!-- GESTION DES CONTACTS -->
174    <div class="menu-group mb-3">
175        <div class="text-uppercase text-secondary small mb-2 px-2">Gestion des contacts</div>
176        <a href="<?= base_url('dashboard/contacts') ?>"><i class="bi bi-person-lines-fill"></i><span>Contacts</span></a>
177        <a href="<?= base_url('dashboard/segments') ?>"><i class="bi bi-diagram-2"></i><span>Segments</span></a>
178        <a href="<?= base_url('dashboard/contact-listes') ?>"><i class="bi bi-list-ul"></i><span>Listes</span></a>
179        <a href="<?= base_url('dashboard/expediteurs') ?>"><i class="bi bi-hdd-network"></i><span>Expéditeurs</span></a>
180    </div>
181
182    <!-- COMMUNICATION -->
183    <div class="menu-group mb-3">
184        <div class="text-uppercase text-secondary small mb-2 px-2">Communication</div>
185        <a href="<?= base_url('dashboard/notification/regles/liste') ?>"><i class="bi bi-diagram-3"></i><span>Règles</span></a>
186        <a href="<?= base_url('dashboard/notification/regles') ?>"><i class="bi bi-bezier2"></i><span>Rule Builder</span></a>
187        <a href="<?= base_url('dashboard/templates') ?>"><i class="bi bi-file-earmark-text"></i><span>Templates</span></a>
188    </div>
189
190    <!-- MONITORING -->
191    <div class="menu-group mb-3">
192        <div class="text-uppercase text-secondary small mb-2 px-2">Monitoring</div>
193        <a href="<?= base_url('dashboard/monitoring/overview') ?>"><i class="bi bi-activity"></i><span>Vue globale</span></a>
194        <a href="<?= base_url('dashboard/monitoring/queue') ?>"><i class="bi bi-hourglass"></i><span>File</span></a>
195        <a href="<?= base_url('dashboard/monitoring/success') ?>"><i class="bi bi-check2-circle"></i><span>Succès</span></a>
196        <a href="<?= base_url('dashboard/monitoring/failed') ?>"><i class="bi bi-x-circle"></i><span>Échecs</span></a>
197        <a href="<?= base_url('dashboard/monitoring/stats') ?>"><i class="bi bi-bar-chart-line"></i><span>Statistiques</span></a>
198        <a href="<?= base_url('dashboard/monitoring/logs') ?>"><i class="bi bi-journal-text"></i><span>Logs</span></a>
199    </div>
200
201    <!-- SYSTEM ACTIONS -->
202    <div class="mt-auto pt-3 border-top">
203        <a href="<?= base_url('dashboard/system') ?>" class="btn btn-dark w-100 mb-2 d-flex align-items-center justify-content-center gap-2">
204            <i class="bi bi-gear-fill"></i><span>Système</span>
205        </a>
206        <a href="<?= base_url('dashboard/updater') ?>" class="btn btn-primary w-100 mb-2 d-flex align-items-center justify-content-center gap-2">
207            <i class="bi bi-arrow-repeat"></i><span>Mise à jour</span>
208        </a>
209        <a href="<?= base_url('dashboard/support') ?>" class="btn btn-success w-100 d-flex align-items-center justify-content-center gap-2">
210            <i class="bi bi-life-preserver"></i><span>Support</span>
211        </a>
212    </div>
213</div>
214
215<!-- CONTENT -->
216<div class="content" id="content">
217
218    <!-- TOPBAR (sans bouton toggle) -->
219    <div class="topbar">
220        <div class="d-flex align-items-center gap-3">
221            <h5 class="mb-0 fw-semibold text-dark"><?= $title ?? 'Tableau de bord' ?></h5>
222        </div>
223
224        <div class="dropdown">
225            <button class="btn btn-light border dropdown-toggle d-flex align-items-center gap-2 px-3 py-2" 
226                    data-bs-toggle="dropdown" style="border-radius: 10px;">
227                <i class="bi bi-person-circle fs-5"></i>
228                <span class="fw-medium">Administrateur</span>
229            </button>
230
231            <ul class="dropdown-menu dropdown-menu-end shadow" style="border-radius: 12px; min-width: 280px;">
232                <li class="dropdown-header">Paramètres globaux</li>
233                <li><a class="dropdown-item" href="<?= base_url('dashboard/profile') ?>"><i class="bi bi-people"></i> Profil</a></li>
234                <li><a class="dropdown-item" href="<?= base_url('dashboard/canaux') ?>"><i class="bi bi-gear-wide-connected"></i> Canaux</a></li>
235
236                <li class="dropdown-divider"></li>
237                <li class="dropdown-header">Providers</li>
238                <li><a class="dropdown-item" href="<?= base_url('dashboard/fournisseurs/sms') ?>"><i class="bi bi-chat-text"></i> SMS / OTP</a></li>
239                <li><a class="dropdown-item" href="<?= base_url('dashboard/fournisseurs/whatsapp') ?>"><i class="bi bi-whatsapp"></i> WhatsApp</a></li>
240                <li><a class="dropdown-item" href="<?= base_url('dashboard/fournisseurs/email') ?>"><i class="bi bi-envelope-at"></i> Email</a></li>
241
242                <li class="dropdown-divider"></li>
243                <li class="dropdown-header">Intégrations</li>
244                <li><a class="dropdown-item" href="<?= base_url('dashboard/integrations') ?>"><i class="bi bi-plug"></i> Liste des intégrations</a></li>
245
246                <li class="dropdown-divider"></li>
247                <li class="dropdown-header fw-bold">Orchestration système</li>
248                <li class="px-3 py-2">
249                    <a href="<?= base_url('dashboard/lancer/cron') ?>" class="btn btn-dark btn-sm w-100 mb-2 d-flex align-items-center justify-content-center gap-2">
250                        <i class="bi bi-clock-history"></i> Exécuter le Cron
251                    </a>
252                    <a href="<?= base_url('dashboard/stream/file') ?>" class="btn btn-primary btn-sm w-100 mb-2 d-flex align-items-center justify-content-center gap-2">
253                        <i class="bi bi-cpu"></i> Supervision
254                    </a>
255                    <a href="<?= base_url('dashboard/system/queue') ?>" class="btn btn-warning btn-sm w-100 d-flex align-items-center justify-content-center gap-2">
256                        <i class="bi bi-list-check"></i> File de traitement
257                    </a>
258                </li>
259
260                <li class="dropdown-divider"></li>
261                <li class="dropdown-header fw-bold">Partager</li>
262                <li class="px-3 py-2">
263                    <button type="button" data-bs-toggle="modal" data-bs-target="#shareAppModal"
264                            class="btn btn-warning btn-sm w-100 d-flex align-items-center justify-content-center gap-2">
265                        <i class="bi bi-share"></i> Partager l’application
266                    </button>
267                </li>
268
269                <li class="dropdown-divider"></li>
270                <li>
271                    <form action="/logout" method="post">
272                        <?= csrf_field() ?>
273                        <button class="dropdown-item text-danger" type="submit">
274                            <i class="bi bi-box-arrow-right"></i> Déconnexion
275                        </button>
276                    </form>
277                </li>
278            </ul>
279        </div>
280    </div>
281
282    <!-- Modal Partager -->
283    <div class="modal fade" id="shareAppModal" tabindex="-1">
284        <div class="modal-dialog modal-dialog-centered">
285            <div class="modal-content">
286                <div class="modal-header">
287                    <h5 class="modal-title">Partager l’application</h5>
288                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
289                </div>
290                <div class="modal-body text-center">
291                    <?php $url = base_url(); ?>
292                    <p class="small text-muted"><?= $url ?></p>
293                    <div class="d-grid gap-2">
294                        <a class="btn btn-success" href="https://wa.me/?text=<?= urlencode('Application : ' . $url) ?>" target="_blank">WhatsApp</a>
295                        <button class="btn btn-secondary" onclick="copyLink()">Copier le lien</button>
296                    </div>
297                </div>
298            </div>
299        </div>
300    </div>
301
302    <!-- CONTENU DES VUES ENFANTS -->
303    <?= $this->renderSection('content') ?>
304
305</div>
306
307<!-- JS -->
308<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
309
310<script>
311    // Anti-flicker : réactivation des transitions après le chargement
312    window.addEventListener('DOMContentLoaded', function() {
313        document.body.classList.remove('preload-transitions-off');
314    });
315
316    window.copyLink = function() {
317        const url = '<?= base_url() ?>';
318        navigator.clipboard.writeText(url).then(() => {
319            alert('Lien copié dans le presse-papier');
320        }).catch(() => {
321            prompt('Copiez manuellement :', url);
322        });
323    };
324</script>
325
326</body>
327</html>