Nouvelle version app
This commit is contained in:
+75
-36
@@ -4,11 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<meta name="theme-color" content="#0D2B5E">
|
<meta name="theme-color" content="#0D2B5E">
|
||||||
<title>CYBERUSGATE - AVM Access</title>
|
<title>CYBERUSGATE - Access</title>
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
|
||||||
<link rel="manifest" href="/site.webmanifest">
|
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
@@ -127,7 +123,7 @@
|
|||||||
/* SELECT */
|
/* SELECT */
|
||||||
select.select-slot { width: 100%; padding: 10px; border-radius: 8px; border: 1px solid var(--gray-3); background: var(--white); color: var(--text-main); font-size: 13px; outline: none; }
|
select.select-slot { width: 100%; padding: 10px; border-radius: 8px; border: 1px solid var(--gray-3); background: var(--white); color: var(--text-main); font-size: 13px; outline: none; }
|
||||||
|
|
||||||
/* MODAL */
|
/* MODALS */
|
||||||
.modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: 1000; align-items: center; justify-content: center; backdrop-filter: blur(3px); opacity: 0; transition: 0.3s; }
|
.modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: 1000; align-items: center; justify-content: center; backdrop-filter: blur(3px); opacity: 0; transition: 0.3s; }
|
||||||
.modal-overlay.open { display: flex; opacity: 1; }
|
.modal-overlay.open { display: flex; opacity: 1; }
|
||||||
.modal-box { background: var(--white); border-radius: 20px; padding: 24px; width: 90%; max-width: 360px; transform: scale(0.9); transition: 0.3s; text-align: center;}
|
.modal-box { background: var(--white); border-radius: 20px; padding: 24px; width: 90%; max-width: 360px; transform: scale(0.9); transition: 0.3s; text-align: center;}
|
||||||
@@ -138,6 +134,10 @@
|
|||||||
/* TOAST */
|
/* TOAST */
|
||||||
.toast { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%) translateY(20px); background: #263238; color: white; padding: 14px 24px; border-radius: 30px; font-size: 14px; font-weight: bold; opacity: 0; transition: 0.3s; z-index: 9999; pointer-events: none; box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
|
.toast { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%) translateY(20px); background: #263238; color: white; padding: 14px 24px; border-radius: 30px; font-size: 14px; font-weight: bold; opacity: 0; transition: 0.3s; z-index: 9999; pointer-events: none; box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
|
||||||
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
||||||
|
|
||||||
|
/* Biometric animation */
|
||||||
|
.bio-icon { color: var(--blue-main); margin-bottom: 16px; animation: pulseBio 2s infinite; }
|
||||||
|
@keyframes pulseBio { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="dark-mode">
|
<body class="dark-mode">
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
<svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
<svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
||||||
</div>
|
</div>
|
||||||
<h1>CYBERUSGATE</h1>
|
<h1>CYBERUSGATE</h1>
|
||||||
<p>Système de contrôle d'accès AVM</p>
|
<p>Système de contrôle d'accès</p>
|
||||||
|
|
||||||
<div class="role-btn" onclick="login('user')">
|
<div class="role-btn" onclick="login('user')">
|
||||||
<div class="role-icon">AD</div>
|
<div class="role-icon">AD</div>
|
||||||
@@ -163,7 +163,7 @@
|
|||||||
<div class="role-icon" style="color: var(--orange);">⚙️</div>
|
<div class="role-icon" style="color: var(--orange);">⚙️</div>
|
||||||
<div class="role-text">
|
<div class="role-text">
|
||||||
<h3>Espace DSI / Admin</h3>
|
<h3>Espace DSI / Admin</h3>
|
||||||
<p>Gestion Infra AVM</p>
|
<p>Gestion Infrastructure</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,7 +176,7 @@
|
|||||||
<div class="avatar" id="header-avatar">AD</div>
|
<div class="avatar" id="header-avatar">AD</div>
|
||||||
<div class="header-info">
|
<div class="header-info">
|
||||||
<h2 id="header-name">Alice Dupont</h2>
|
<h2 id="header-name">Alice Dupont</h2>
|
||||||
<p id="header-role">Utilisateur AVM</p>
|
<p id="header-role">Utilisateur Interne</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="logout-btn" onclick="logout()">Quitter</button>
|
<button class="logout-btn" onclick="logout()">Quitter</button>
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
<nav class="nav-tabs" id="nav-admin" style="display:none;">
|
<nav class="nav-tabs" id="nav-admin" style="display:none;">
|
||||||
<button class="nav-tab active" onclick="switchTab('admin-dash', this)">
|
<button class="nav-tab active" onclick="switchTab('admin-dash', this)">
|
||||||
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
|
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
|
||||||
Infra AVM
|
Infrastructure
|
||||||
</button>
|
</button>
|
||||||
<button class="nav-tab" onclick="switchTab('admin-users', this)">
|
<button class="nav-tab" onclick="switchTab('admin-users', this)">
|
||||||
<svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75"/></svg>
|
<svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75"/></svg>
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
<div id="tab-user-add" class="tab-content">
|
<div id="tab-user-add" class="tab-content">
|
||||||
<div class="card" style="text-align: center;">
|
<div class="card" style="text-align: center;">
|
||||||
<h2 style="margin-bottom:10px;">Ajouter un badge</h2>
|
<h2 style="margin-bottom:10px;">Ajouter un badge</h2>
|
||||||
<p style="font-size:14px; color:var(--text-sub); margin-bottom:24px;">Demandez à votre DSI de générer un QR code d'invitation pour provisionner votre téléphone.</p>
|
<p style="font-size:14px; color:var(--text-sub); margin-bottom:24px;">Demandez à votre administrateur système de générer un QR code d'invitation pour provisionner votre téléphone.</p>
|
||||||
|
|
||||||
<div style="width:200px; height:200px; background:var(--gray-2); border-radius:16px; margin:0 auto 24px; display:flex; align-items:center; justify-content:center; border:2px dashed var(--gray-4);">
|
<div style="width:200px; height:200px; background:var(--gray-2); border-radius:16px; margin:0 auto 24px; display:flex; align-items:center; justify-content:center; border:2px dashed var(--gray-4);">
|
||||||
<svg viewBox="0 0 24 24" style="width:48px; fill:none; stroke:var(--gray-4); stroke-width:2;"><path d="M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4z"/><path d="M14 14l6 6M20 14l-6 6"/></svg>
|
<svg viewBox="0 0 24 24" style="width:48px; fill:none; stroke:var(--gray-4); stroke-width:2;"><path d="M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4z"/><path d="M14 14l6 6M20 14l-6 6"/></svg>
|
||||||
@@ -243,17 +243,17 @@
|
|||||||
|
|
||||||
<div id="tab-admin-dash" class="tab-content">
|
<div id="tab-admin-dash" class="tab-content">
|
||||||
<div class="stat-grid">
|
<div class="stat-grid">
|
||||||
<div class="stat-box"><div class="num" id="stat-machines">190</div><div class="lbl">Machines AVM</div></div>
|
<div class="stat-box"><div class="num" id="stat-machines">190</div><div class="lbl">Équipements</div></div>
|
||||||
<div class="stat-box" style="border-color:var(--green);"><div class="num" id="stat-users">30</div><div class="lbl">Utilisateurs</div></div>
|
<div class="stat-box" style="border-color:var(--green);"><div class="num" id="stat-users">30</div><div class="lbl">Utilisateurs</div></div>
|
||||||
<div class="stat-box" style="border-color:var(--orange);"><div class="num" id="stat-badges">--</div><div class="lbl">Badges Actifs</div></div>
|
<div class="stat-box" style="border-color:var(--orange);"><div class="num" id="stat-badges">--</div><div class="lbl">Badges Actifs</div></div>
|
||||||
<div class="stat-box" style="border-color:var(--red);"><div class="num" id="stat-invites">--</div><div class="lbl">QR Actifs</div></div>
|
<div class="stat-box" style="border-color:var(--red);"><div class="num" id="stat-invites">--</div><div class="lbl">QR Actifs</div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-title">État de l'infrastructure</div>
|
<div class="card-title">État du système</div>
|
||||||
<div style="font-size:13px; color:var(--text-sub); display:flex; flex-direction:column; gap:12px;">
|
<div style="font-size:13px; color:var(--text-sub); display:flex; flex-direction:column; gap:12px;">
|
||||||
<div style="display:flex; justify-content:space-between;"><span>Synchro AD (LAPS)</span><span style="color:var(--green);font-weight:bold;">Opérationnelle</span></div>
|
<div style="display:flex; justify-content:space-between;"><span>Synchro Active Directory</span><span style="color:var(--green);font-weight:bold;">Opérationnelle</span></div>
|
||||||
<div style="display:flex; justify-content:space-between;"><span>Migration SharePoint</span><span style="color:var(--orange);font-weight:bold;">2.41 TO / En cours</span></div>
|
<div style="display:flex; justify-content:space-between;"><span>Chiffrement AES-256</span><span style="color:var(--green);font-weight:bold;">Actif</span></div>
|
||||||
<div style="display:flex; justify-content:space-between;"><span>Contrôleurs de Domaine</span><span style="color:var(--green);font-weight:bold;">En ligne</span></div>
|
<div style="display:flex; justify-content:space-between;"><span>Contrôleurs de Domaine</span><span style="color:var(--green);font-weight:bold;">En ligne</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -261,7 +261,7 @@
|
|||||||
|
|
||||||
<div id="tab-admin-users" class="tab-content">
|
<div id="tab-admin-users" class="tab-content">
|
||||||
<div class="card" style="padding:0; overflow:hidden;">
|
<div class="card" style="padding:0; overflow:hidden;">
|
||||||
<div style="padding:16px; background:var(--gray-2); font-weight:bold; font-size:14px;">Annuaire AVM</div>
|
<div style="padding:16px; background:var(--gray-2); font-weight:bold; font-size:14px;">Annuaire Utilisateurs</div>
|
||||||
<div id="admin-user-list">
|
<div id="admin-user-list">
|
||||||
<!-- Generated via JS -->
|
<!-- Generated via JS -->
|
||||||
</div>
|
</div>
|
||||||
@@ -286,6 +286,27 @@
|
|||||||
|
|
||||||
<!-- ===== MODALS ===== -->
|
<!-- ===== MODALS ===== -->
|
||||||
|
|
||||||
|
<!-- 2MFA / Biometric Overlay (Apple Pay Style) -->
|
||||||
|
<div class="modal-overlay" id="modal-biometric" onclick="if(event.target===this)cancelBiometric()">
|
||||||
|
<div class="modal-box" style="max-width:320px;">
|
||||||
|
<div class="bio-icon">
|
||||||
|
<svg viewBox="0 0 24 24" width="64" height="64" stroke="currentColor" fill="none" stroke-width="1.5">
|
||||||
|
<path d="M12 2a10 10 0 0 0-10 10c0 5.523 4.477 10 10 10s10-4.477 10-10A10 10 0 0 0 12 2z"/>
|
||||||
|
<path d="M8 14s1.5 2 4 2 4-2 4-2"/>
|
||||||
|
<line x1="9" y1="9" x2="9.01" y2="9"/>
|
||||||
|
<line x1="15" y1="9" x2="15.01" y2="9"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h2 style="margin-bottom:8px; font-size:18px;">Face ID / Touch ID</h2>
|
||||||
|
<p style="font-size:13px; color:var(--text-sub); margin-bottom:24px;">Confirmez votre identité pour libérer l'accès NFC.</p>
|
||||||
|
|
||||||
|
<button class="btn btn-primary" onclick="confirmBiometric()" style="margin-bottom:12px;">
|
||||||
|
S'authentifier
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-outline" onclick="cancelBiometric()">Annuler</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Admin Manage User Modal -->
|
<!-- Admin Manage User Modal -->
|
||||||
<div class="modal-overlay" id="modal-manage-user" onclick="if(event.target===this)closeModal('modal-manage-user')">
|
<div class="modal-overlay" id="modal-manage-user" onclick="if(event.target===this)closeModal('modal-manage-user')">
|
||||||
<div class="modal-box" style="max-width:400px; text-align:left;">
|
<div class="modal-box" style="max-width:400px; text-align:left;">
|
||||||
@@ -305,7 +326,6 @@
|
|||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
<h2>QR d'Invitation</h2>
|
<h2>QR d'Invitation</h2>
|
||||||
<div class="qr-placeholder">
|
<div class="qr-placeholder">
|
||||||
<!-- Fake QR visual with SVG -->
|
|
||||||
<svg width="150" height="150" viewBox="0 0 24 24" fill="var(--text-main)"><path d="M3 3h8v8H3zm2 2v4h4V5zm8-2h8v8h-8zm2 2v4h4V5zM3 13h8v8H3zm2 2v4h4v-4zm13-2h2v2h-2zm-2 2h2v2h-2zm2 2h2v2h-2zm-4 0h2v2h-2zm2 2h2v2h-2zm-4-4h2v2h-2zm2-2h2v2h-2z"/></svg>
|
<svg width="150" height="150" viewBox="0 0 24 24" fill="var(--text-main)"><path d="M3 3h8v8H3zm2 2v4h4V5zm8-2h8v8h-8zm2 2v4h4V5zM3 13h8v8H3zm2 2v4h4v-4zm13-2h2v2h-2zm-2 2h2v2h-2zm2 2h2v2h-2zm-4 0h2v2h-2zm2 2h2v2h-2zm-4-4h2v2h-2zm2-2h2v2h-2z"/></svg>
|
||||||
</div>
|
</div>
|
||||||
<p style="font-weight:bold; color:var(--green); margin-bottom:4px;" id="qr-expiry">Expire dans 14:59</p>
|
<p style="font-weight:bold; color:var(--green); margin-bottom:4px;" id="qr-expiry">Expire dans 14:59</p>
|
||||||
@@ -315,27 +335,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="toast" id="toast"></div>
|
<div class="toast" id="toast"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// ===== DATABASE / STATE =====
|
// ===== DATABASE / STATE =====
|
||||||
const defaultDB = {
|
const defaultDB = {
|
||||||
users: [
|
users: [
|
||||||
{ id: 'u1', name: 'Alice Dupont', email: 'alice@avm.com', role: 'user', avatar: 'AD' },
|
{ id: 'u1', name: 'Alice Dupont', email: 'alice@societe.fr', role: 'user', avatar: 'AD' },
|
||||||
{ id: 'u2', name: 'Responsable Infra', email: 'admin@avm.com', role: 'admin', avatar: '⚙️' }
|
{ id: 'u2', name: 'Administrateur', email: 'admin@societe.fr', role: 'admin', avatar: '⚙️' }
|
||||||
],
|
],
|
||||||
badges: [
|
badges: [
|
||||||
{ id: 'b1', userId: 'u1', name: 'Pass AVM Principal', tech: 'NFC', active: true, timeSlot: '247' }
|
{ id: 'b1', userId: 'u1', name: 'Pass Sécurité Principal', tech: 'NFC', active: true, timeSlot: '247' }
|
||||||
],
|
],
|
||||||
invitations: []
|
invitations: []
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = JSON.parse(localStorage.getItem('sa_db_v3')) || defaultDB;
|
// Changed version key to ensure fresh start without previous AVM data
|
||||||
|
let db = JSON.parse(localStorage.getItem('sa_db_v4')) || defaultDB;
|
||||||
let currentUser = null;
|
let currentUser = null;
|
||||||
|
|
||||||
function saveDb() {
|
function saveDb() {
|
||||||
localStorage.setItem('sa_db_v3', JSON.stringify(db));
|
localStorage.setItem('sa_db_v4', JSON.stringify(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== PWA SETUP =====
|
// ===== PWA SETUP =====
|
||||||
@@ -357,7 +377,7 @@ function login(roleType) {
|
|||||||
currentUser = db.users.find(u => u.role === roleType);
|
currentUser = db.users.find(u => u.role === roleType);
|
||||||
document.getElementById('header-avatar').innerText = currentUser.avatar;
|
document.getElementById('header-avatar').innerText = currentUser.avatar;
|
||||||
document.getElementById('header-name').innerText = currentUser.name;
|
document.getElementById('header-name').innerText = currentUser.name;
|
||||||
document.getElementById('header-role').innerText = roleType === 'admin' ? "DSI / Infra" : "Utilisateur";
|
document.getElementById('header-role').innerText = roleType === 'admin' ? "DSI / Infra" : "Utilisateur Interne";
|
||||||
|
|
||||||
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
|
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
|
||||||
document.getElementById('screen-app').classList.add('active');
|
document.getElementById('screen-app').classList.add('active');
|
||||||
@@ -396,7 +416,7 @@ function switchTab(tabId, btnElement) {
|
|||||||
if(tabId === 'admin-qr') renderActiveInvites();
|
if(tabId === 'admin-qr') renderActiveInvites();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== USER VIEWS =====
|
// ===== USER VIEWS & BIOMETRICS =====
|
||||||
function renderUserBadges() {
|
function renderUserBadges() {
|
||||||
const container = document.getElementById('user-badges-container');
|
const container = document.getElementById('user-badges-container');
|
||||||
const myBadges = db.badges.filter(b => b.userId === currentUser.id);
|
const myBadges = db.badges.filter(b => b.userId === currentUser.id);
|
||||||
@@ -408,8 +428,8 @@ function renderUserBadges() {
|
|||||||
|
|
||||||
container.innerHTML = myBadges.map(b => `
|
container.innerHTML = myBadges.map(b => `
|
||||||
<div class="virtual-badge" style="${!b.active ? 'filter: grayscale(1); opacity:0.7;' : ''}">
|
<div class="virtual-badge" style="${!b.active ? 'filter: grayscale(1); opacity:0.7;' : ''}">
|
||||||
<div class="company">CYBERUSGATE - AVM Infra</div>
|
<div class="company">CYBERUSGATE - SECURE INFRA</div>
|
||||||
<div class="nfc-icon" onclick="${b.active ? 'simulateNFC()' : 'showToast(\'Ce badge a été désactivé par l\\\\\'administrateur\')'}">
|
<div class="nfc-icon" onclick="${b.active ? 'triggerBiometricAuth()' : 'showToast(\'Ce badge a été désactivé par l\\\\\'administrateur\')'}">
|
||||||
<svg viewBox="0 0 24 24" width="40" stroke="currentColor" fill="none" stroke-width="2"><path d="M12 4C8 4 4 8 4 12s4 8 8 8 8-4 8-8"/><circle cx="12" cy="12" r="2" fill="currentColor"/></svg>
|
<svg viewBox="0 0 24 24" width="40" stroke="currentColor" fill="none" stroke-width="2"><path d="M12 4C8 4 4 8 4 12s4 8 8 8 8-4 8-8"/><circle cx="12" cy="12" r="2" fill="currentColor"/></svg>
|
||||||
</div>
|
</div>
|
||||||
<h3>${b.name}</h3>
|
<h3>${b.name}</h3>
|
||||||
@@ -419,9 +439,30 @@ function renderUserBadges() {
|
|||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function simulateNFC() {
|
// Intercept NFC with Biometric 2MFA Modal
|
||||||
if(navigator.vibrate) navigator.vibrate(100);
|
function triggerBiometricAuth() {
|
||||||
showToast("✓ Communication NFC établie avec le lecteur");
|
if(navigator.vibrate) navigator.vibrate(50);
|
||||||
|
document.getElementById('modal-biometric').classList.add('open');
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelBiometric() {
|
||||||
|
document.getElementById('modal-biometric').classList.remove('open');
|
||||||
|
showToast("❌ Authentification annulée");
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmBiometric() {
|
||||||
|
// Close modal
|
||||||
|
document.getElementById('modal-biometric').classList.remove('open');
|
||||||
|
|
||||||
|
// Simulate successful biometric read and subsequent NFC transmission
|
||||||
|
if(navigator.vibrate) navigator.vibrate([50, 50, 100]);
|
||||||
|
showToast("✓ Identité confirmée. Transmission NFC en cours...");
|
||||||
|
|
||||||
|
// After short delay, show success of access
|
||||||
|
setTimeout(() => {
|
||||||
|
showToast("🟢 Accès Autorisé au lecteur");
|
||||||
|
if(navigator.vibrate) navigator.vibrate(200);
|
||||||
|
}, 1200);
|
||||||
}
|
}
|
||||||
|
|
||||||
function simulateScanQR() {
|
function simulateScanQR() {
|
||||||
@@ -431,17 +472,16 @@ function simulateScanQR() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const invite = validInvites.pop(); // Consume the latest
|
const invite = validInvites.pop();
|
||||||
db.invitations = db.invitations.filter(i => i.id !== invite.id); // Remove it
|
db.invitations = db.invitations.filter(i => i.id !== invite.id);
|
||||||
|
|
||||||
// Create badge
|
|
||||||
const newBadge = {
|
const newBadge = {
|
||||||
id: 'B' + Math.floor(Math.random()*10000),
|
id: 'B' + Math.floor(Math.random()*10000),
|
||||||
userId: currentUser.id,
|
userId: currentUser.id,
|
||||||
name: 'Nouveau Badge AVM',
|
name: 'Nouveau Badge Sécurisé',
|
||||||
tech: 'NFC',
|
tech: 'NFC',
|
||||||
active: true,
|
active: true,
|
||||||
timeSlot: 'office' // default
|
timeSlot: 'office'
|
||||||
};
|
};
|
||||||
|
|
||||||
db.badges.push(newBadge);
|
db.badges.push(newBadge);
|
||||||
@@ -451,7 +491,6 @@ function simulateScanQR() {
|
|||||||
switchTab('user-badge', document.querySelectorAll('#nav-user .nav-tab')[0]);
|
switchTab('user-badge', document.querySelectorAll('#nav-user .nav-tab')[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===== ADMIN VIEWS =====
|
// ===== ADMIN VIEWS =====
|
||||||
function updateAdminDash() {
|
function updateAdminDash() {
|
||||||
document.getElementById('stat-badges').innerText = db.badges.length;
|
document.getElementById('stat-badges').innerText = db.badges.length;
|
||||||
|
|||||||
Reference in New Issue
Block a user