Files
Lucas/checklist.php
Debian 24dbc7cd6a Initial commit — Serveur Lucas SmartEye
API réception alertes chute (SmartEye/YOLO), analyse IA (Gemini 2.5 Flash),
gestion alertes avec escalade (watchdog), notifications Firebase,
dashboard web, documentation MkDocs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 21:26:06 +01:00

495 lines
44 KiB
PHP

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SmartEye Checklist Installation</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body { background: #0a0e1a; }
.badge-smarteye { background: #f59e0b22; color: #fbbf24; border: 1px solid #f59e0b44; }
.badge-lucas { background: #10b98122; color: #34d399; border: 1px solid #10b98144; }
.badge-ava { background: #6366f122; color: #818cf8; border: 1px solid #6366f144; }
.check-done:checked { accent-color: #10b981; }
.check-tested:checked { accent-color: #3b82f6; }
.phase-bar-smarteye { border-left: 3px solid #f59e0b; }
.phase-bar-lucas { border-left: 3px solid #10b981; }
.phase-bar-ava { border-left: 3px solid #6366f1; }
.phase-bar-all { border-left: 3px solid #8b5cf6; }
.row-done { opacity: 0.5; }
.row-done td { text-decoration: line-through; text-decoration-color: #475569; }
.row-done .no-strike { text-decoration: none; }
@keyframes pulse-border { 0%,100% { border-color: #ef444488; } 50% { border-color: #ef4444; } }
.pending-critical { animation: pulse-border 2s infinite; }
.progress-fill { transition: width 0.5s ease; }
</style>
</head>
<body class="min-h-screen text-slate-200">
<!-- HEADER -->
<nav class="bg-slate-900/80 backdrop-blur border-b border-slate-800 px-6 py-4 sticky top-0 z-50">
<div class="max-w-6xl mx-auto flex justify-between items-center">
<div class="flex items-center gap-4">
<div class="w-3 h-3 rounded-full bg-emerald-500"></div>
<span class="font-bold text-xl tracking-wider text-white">CHECKLIST <span class="text-slate-500 text-sm font-normal">INSTALLATION</span></span>
</div>
<div class="flex items-center gap-4">
<div class="flex gap-2 text-xs">
<span class="badge-smarteye px-2 py-1 rounded font-bold">SmartEye</span>
<span class="badge-lucas px-2 py-1 rounded font-bold">Lucas</span>
<span class="badge-ava px-2 py-1 rounded font-bold">AVA</span>
</div>
<select id="client-select" onchange="loadClient()" class="bg-slate-800 border border-slate-700 text-white text-sm rounded px-3 py-2">
<option value="">-- Client --</option>
<?php
$db = json_decode(file_get_contents('database.json'), true);
foreach ($db['clients'] as $id => $c) {
echo '<option value="' . htmlspecialchars($id) . '">' . htmlspecialchars($c['name']) . '</option>';
}
?>
</select>
<a href="admin.php" class="text-slate-400 hover:text-white text-sm border border-slate-700 px-3 py-2 rounded transition">Admin</a>
</div>
</div>
</nav>
<!-- PROGRESS BAR -->
<div class="max-w-6xl mx-auto px-6 mt-6">
<div class="bg-slate-900 rounded-xl border border-slate-800 p-4">
<div class="flex justify-between items-center mb-2">
<span class="text-sm text-slate-400">Progression globale</span>
<span id="progress-text" class="text-sm font-bold text-emerald-400">0 / 0</span>
</div>
<div class="w-full bg-slate-800 rounded-full h-3 overflow-hidden">
<div id="progress-bar" class="progress-fill bg-gradient-to-r from-emerald-600 to-emerald-400 h-full rounded-full" style="width: 0%"></div>
</div>
<div class="flex justify-between mt-2 text-xs text-slate-600">
<span>Bureau</span>
<span>Sur place</span>
<span>Config App</span>
<span>Tunnels</span>
<span>Tests</span>
<span>Production</span>
</div>
</div>
</div>
<!-- CHECKLIST -->
<div class="max-w-6xl mx-auto px-6 py-6 space-y-6">
<!-- PHASE 1 : BUREAU -->
<div class="bg-slate-900 rounded-xl border border-slate-800 overflow-hidden">
<div class="px-5 py-3 bg-slate-800/50 flex items-center gap-3">
<span class="text-lg">🏢</span>
<h2 class="font-bold text-white text-sm uppercase tracking-wider">Phase 1 — Au Bureau</h2>
<span class="text-xs text-slate-500 ml-auto">Avant le d&eacute;placement</span>
</div>
<table class="w-full text-sm">
<thead class="text-xs text-slate-500 uppercase bg-slate-950/50">
<tr>
<th class="px-5 py-2 text-left w-8">Fait</th>
<th class="px-2 py-2 text-left w-8">Test</th>
<th class="px-3 py-2 text-left">Action</th>
<th class="px-3 py-2 text-left w-24">Qui</th>
<th class="px-3 py-2 text-left w-48">Notes</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-800/50">
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-1">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">Cr&eacute;er le dossier client dans <span class="text-emerald-400 font-mono text-xs">admin.php</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-2">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">G&eacute;n&eacute;rer le mot de passe LucasApp <span class="text-slate-600 text-xs">(admin/generate_password.php)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-3">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">Remplir infos senior (nom, adresse, date naissance)</td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-4">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">Ajouter contacts famille (noms, t&eacute;l, OS)</td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-5">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Pr&eacute;parer le Jetson <span class="text-slate-600 text-xs">(flash SSD, OS, drivers)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-5b">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Pr&eacute;-configurer WiFi hotspot <span class="font-mono text-xs text-amber-400">SmartEye-Setup</span> <span class="text-slate-600 text-xs">(connexion sans &eacute;cran)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="SSID: SmartEye-Setup / MDP: smarteye2026" onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-5c">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Pr&eacute;parer cl&eacute; USB auto-config WiFi <span class="text-slate-600 text-xs">(script + wifi.conf du client)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="SSID + MDP du client" onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-6">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">V&eacute;rifier que SmartEye tourne <span class="text-slate-600 text-xs">(service actif, YOLO charg&eacute;)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="bureau-7">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Pr&eacute;parer les cam&eacute;ras <span class="text-slate-600 text-xs">(reset usine, config 2 flux RTSP)</span> <a href="doc_camera.php" target="_blank" class="text-amber-400 hover:text-amber-300 text-xs ml-1">[guide]</a></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
</tbody>
</table>
</div>
<!-- PHASE 2 : SUR PLACE - HARDWARE -->
<div class="bg-slate-900 rounded-xl border border-slate-800 overflow-hidden">
<div class="px-5 py-3 bg-slate-800/50 flex items-center gap-3">
<span class="text-lg">🏠</span>
<h2 class="font-bold text-white text-sm uppercase tracking-wider">Phase 2 — Sur Place : Mat&eacute;riel</h2>
<span class="text-xs text-slate-500 ml-auto">Installation physique</span>
</div>
<table class="w-full text-sm">
<thead class="text-xs text-slate-500 uppercase bg-slate-950/50">
<tr><th class="px-5 py-2 text-left w-8">Fait</th><th class="px-2 py-2 text-left w-8">Test</th><th class="px-3 py-2 text-left">Action</th><th class="px-3 py-2 text-left w-24">Qui</th><th class="px-3 py-2 text-left w-48">Notes</th></tr>
</thead>
<tbody class="divide-y divide-slate-800/50">
<tr class="task-row hover:bg-slate-800/30" data-task="place-1">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Alimenter le Jetson + connecter au r&eacute;seau <span class="text-slate-600 text-xs">(hotspot OU cl&eacute; USB OU Ethernet)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="M&eacute;thode utilis&eacute;e : ..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="place-1b">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">SSH sur le Jetson &rarr; configurer WiFi client <span class="font-mono text-xs text-slate-600">nmcli dev wifi connect "SSID" password "***"</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="IP obtenue : ..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="place-2">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Installer et positionner les cam&eacute;ras</td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="Nb cam&eacute;ras : ..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="place-3">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">Renseigner IP Jetson + IPs cam&eacute;ras + ports tunnel dans <span class="text-emerald-400 font-mono text-xs">admin.php</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="Ports : 8560, 8561..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="place-4">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">V&eacute;rifier que SmartEye d&eacute;tecte les cam&eacute;ras (YOLO actif)</td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
</tbody>
</table>
</div>
<!-- PHASE 3 : CONFIG APP AVA -->
<div class="bg-slate-900 rounded-xl border border-slate-800 overflow-hidden">
<div class="px-5 py-3 bg-slate-800/50 flex items-center gap-3">
<span class="text-lg">📱</span>
<h2 class="font-bold text-white text-sm uppercase tracking-wider">Phase 3 — Configuration App AVA</h2>
<span class="text-xs text-slate-500 ml-auto">Sur le t&eacute;l&eacute;phone famille</span>
</div>
<table class="w-full text-sm">
<thead class="text-xs text-slate-500 uppercase bg-slate-950/50">
<tr><th class="px-5 py-2 text-left w-8">Fait</th><th class="px-2 py-2 text-left w-8">Test</th><th class="px-3 py-2 text-left">Action</th><th class="px-3 py-2 text-left w-24">Qui</th><th class="px-3 py-2 text-left w-48">Notes</th></tr>
</thead>
<tbody class="divide-y divide-slate-800/50">
<tr class="task-row hover:bg-slate-800/30" data-task="app-1">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">Saisir identifiant + mot de passe dans AVA</td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="app-2">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-all pl-5">V&eacute;rifier r&eacute;ception <span class="font-mono text-xs text-indigo-400">smarteye_token</span> + <span class="font-mono text-xs text-indigo-400">jetson_ip</span> + <span class="font-mono text-xs text-indigo-400">cameras</span></td>
<td class="px-3 py-3 no-strike">
<span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span>
<span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold ml-1">Lucas</span>
</td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="app-3">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">Scanner cam&eacute;ras via Jetson <span class="text-slate-600 text-xs">(WiFi local : http://jetson_ip:8080)</span></td>
<td class="px-3 py-3 no-strike">
<span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span>
<span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold ml-1">SmartEye</span>
</td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="app-4">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">V&eacute;rifier affichage cam&eacute;ra en local (WiFi)</td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
</tbody>
</table>
</div>
<!-- PHASE 4 : TUNNELS SSH -->
<div class="bg-slate-900 rounded-xl border border-slate-800 overflow-hidden">
<div class="px-5 py-3 bg-slate-800/50 flex items-center gap-3">
<span class="text-lg">🔗</span>
<h2 class="font-bold text-white text-sm uppercase tracking-wider">Phase 4 — Tunnels SSH (acc&egrave;s distant)</h2>
<span class="text-xs text-slate-500 ml-auto">Jetson &rarr; OVH</span>
</div>
<table class="w-full text-sm">
<thead class="text-xs text-slate-500 uppercase bg-slate-950/50">
<tr><th class="px-5 py-2 text-left w-8">Fait</th><th class="px-2 py-2 text-left w-8">Test</th><th class="px-3 py-2 text-left">Action</th><th class="px-3 py-2 text-left w-24">Qui</th><th class="px-3 py-2 text-left w-48">Notes</th></tr>
</thead>
<tbody class="divide-y divide-slate-800/50">
<tr class="task-row hover:bg-slate-800/30" data-task="tunnel-1">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">Cl&eacute; SSH du Jetson ajout&eacute;e dans <span class="font-mono text-xs text-emerald-400">authorized_keys</span> sur OVH</td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="tunnel-2">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Lancer <span class="font-mono text-xs text-amber-400">autossh</span> sur le Jetson avec les ports cam&eacute;ras</td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="-R 8560:ip:554 ..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="tunnel-3">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">V&eacute;rifier ports actifs sur OVH <span class="text-slate-600 text-xs">(ss -tlnp)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="tunnel-4">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Configurer autossh en service (red&eacute;marrage auto)</td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="systemd service" onchange="saveState()"></td>
</tr>
</tbody>
</table>
</div>
<!-- PHASE 5 : TESTS COMPLETS -->
<div class="bg-slate-900 rounded-xl border border-slate-800 overflow-hidden">
<div class="px-5 py-3 bg-slate-800/50 flex items-center gap-3">
<span class="text-lg">🧪</span>
<h2 class="font-bold text-white text-sm uppercase tracking-wider">Phase 5 — Tests Complets</h2>
<span class="text-xs text-slate-500 ml-auto">Couper WiFi, tester en 4G</span>
</div>
<table class="w-full text-sm">
<thead class="text-xs text-slate-500 uppercase bg-slate-950/50">
<tr><th class="px-5 py-2 text-left w-8">Fait</th><th class="px-2 py-2 text-left w-8">Test</th><th class="px-3 py-2 text-left">Action</th><th class="px-3 py-2 text-left w-24">Qui</th><th class="px-3 py-2 text-left w-48">Notes</th></tr>
</thead>
<tbody class="divide-y divide-slate-800/50">
<tr class="task-row hover:bg-slate-800/30" data-task="test-1">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">Cam&eacute;ra live &agrave; distance <span class="text-slate-600 text-xs">(rtsp://57.128.74.87:port)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="test-2">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-smarteye pl-5">Simuler une chute (passer devant cam&eacute;ra, se coucher)</td>
<td class="px-3 py-3 no-strike"><span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="test-3">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">V&eacute;rifier r&eacute;ception image + analyse Gemini <span class="text-slate-600 text-xs">(api.php &rarr; analyze.py)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="test-4">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">R&eacute;ception notification push Firebase</td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="test-5">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">Consulter photos captur&eacute;es <span class="text-slate-600 text-xs">(photos.php)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="test-6">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">Acquitter l'alerte <span class="text-slate-600 text-xs">(acknowledge.php)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="test-7">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-ava pl-5">R&eacute;soudre / reset l'alerte <span class="text-slate-600 text-xs">(reset.php)</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
</tbody>
</table>
</div>
<!-- PHASE 6 : MISE EN PRODUCTION -->
<div class="bg-slate-900 rounded-xl border border-slate-800 overflow-hidden">
<div class="px-5 py-3 bg-slate-800/50 flex items-center gap-3">
<span class="text-lg">🚀</span>
<h2 class="font-bold text-white text-sm uppercase tracking-wider">Phase 6 — Mise en Production</h2>
<span class="text-xs text-slate-500 ml-auto">Validation finale</span>
</div>
<table class="w-full text-sm">
<thead class="text-xs text-slate-500 uppercase bg-slate-950/50">
<tr><th class="px-5 py-2 text-left w-8">Fait</th><th class="px-2 py-2 text-left w-8">Test</th><th class="px-3 py-2 text-left">Action</th><th class="px-3 py-2 text-left w-24">Qui</th><th class="px-3 py-2 text-left w-48">Notes</th></tr>
</thead>
<tbody class="divide-y divide-slate-800/50">
<tr class="task-row hover:bg-slate-800/30" data-task="prod-1">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-lucas pl-5">Passer <span class="font-mono text-xs text-emerald-400">site_status</span> &agrave; <span class="text-emerald-400 font-bold">"active"</span></td>
<td class="px-3 py-3 no-strike"><span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold">Lucas</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="prod-2">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-all pl-5">Former la famille &agrave; l'utilisation de AVA</td>
<td class="px-3 py-3 no-strike"><span class="badge-ava px-2 py-0.5 rounded text-xs font-bold">AVA</span></td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
<tr class="task-row hover:bg-slate-800/30" data-task="prod-3">
<td class="px-5 py-3 no-strike"><input type="checkbox" class="check-done w-4 h-4" onchange="saveState()"></td>
<td class="px-2 py-3 no-strike"><input type="checkbox" class="check-tested w-4 h-4" onchange="saveState()"></td>
<td class="px-3 py-3 phase-bar-all pl-5">PV de recette sign&eacute; par la famille</td>
<td class="px-3 py-3 no-strike">
<span class="badge-smarteye px-2 py-0.5 rounded text-xs font-bold">SmartEye</span>
<span class="badge-lucas px-2 py-0.5 rounded text-xs font-bold ml-1">Lucas</span>
<span class="badge-ava px-2 py-0.5 rounded text-xs font-bold ml-1">AVA</span>
</td>
<td class="px-3 py-3 no-strike"><input type="text" class="note-input w-full bg-transparent border-b border-slate-700 text-xs text-slate-400 px-1 py-0.5 focus:border-slate-500 outline-none" placeholder="..." onchange="saveState()"></td>
</tr>
</tbody>
</table>
</div>
<!-- RESET -->
<div class="text-center py-4">
<button onclick="if(confirm('Remettre toute la checklist à zéro ?')){localStorage.removeItem(getStorageKey());location.reload();}" class="text-xs text-slate-600 hover:text-red-400 transition border border-slate-800 px-4 py-2 rounded">Remettre &agrave; z&eacute;ro</button>
</div>
</div>
<script>
function getStorageKey() {
const client = document.getElementById('client-select').value || '_default';
return 'checklist_' + client;
}
function saveState() {
const state = {};
document.querySelectorAll('.task-row').forEach(row => {
const task = row.dataset.task;
const done = row.querySelector('.check-done').checked;
const tested = row.querySelector('.check-tested').checked;
const note = row.querySelector('.note-input').value;
state[task] = { done, tested, note };
if (done && tested) {
row.classList.add('row-done');
} else {
row.classList.remove('row-done');
}
});
localStorage.setItem(getStorageKey(), JSON.stringify(state));
updateProgress();
}
function loadState() {
const saved = localStorage.getItem(getStorageKey());
if (!saved) return;
const state = JSON.parse(saved);
document.querySelectorAll('.task-row').forEach(row => {
const task = row.dataset.task;
if (state[task]) {
row.querySelector('.check-done').checked = state[task].done;
row.querySelector('.check-tested').checked = state[task].tested;
row.querySelector('.note-input').value = state[task].note || '';
if (state[task].done && state[task].tested) {
row.classList.add('row-done');
}
}
});
updateProgress();
}
function loadClient() {
// Reset all checkboxes and notes
document.querySelectorAll('.task-row').forEach(row => {
row.querySelector('.check-done').checked = false;
row.querySelector('.check-tested').checked = false;
row.querySelector('.note-input').value = '';
row.classList.remove('row-done');
});
loadState();
}
function updateProgress() {
const rows = document.querySelectorAll('.task-row');
const total = rows.length;
let completed = 0;
rows.forEach(row => {
if (row.querySelector('.check-done').checked && row.querySelector('.check-tested').checked) {
completed++;
}
});
const pct = total > 0 ? Math.round((completed / total) * 100) : 0;
document.getElementById('progress-bar').style.width = pct + '%';
document.getElementById('progress-text').textContent = completed + ' / ' + total + ' (' + pct + '%)';
}
// Init
loadState();
</script>
</body>
</html>