Loading module/Evenementiel/view/evenementiel/evenement/afficher.phtml +51 −13 Changes for module/Evenementiel/view/evenementiel/evenement/afficher.phtml: 51 added lines, 13 removed lines. Original line number Diff line number Diff line Loading @@ -144,57 +144,95 @@ $canModifierInscription = $this->isAllowed(EvenementielinscriptionPrivileges::ge </div> </div> <!-- ONGLET :: TAB ------------------------------------------------------------------------------------------------> <!-- ONGLET :: TAB --> <div class="nav nav-tabs" id="nav-tab" role="tablist"> <button class="nav-link active" id="inscriptions-tab" data-bs-toggle="tab" data-bs-target="#inscriptions" type="button" role="tab" aria-controls="inscriptions" aria-selected="true"> Inscription et listes </button> <?php if ($canModifierInscription): ?> <button class="nav-link" id="scan-tab" data-bs-toggle="tab" data-bs-target="#scan" type="button" role="tab" aria-controls="scan" aria-selected="true"> type="button" role="tab" aria-controls="scan" aria-selected="false"> Scan </button> <button class="nav-link" id="pointage-tab" data-bs-toggle="tab" data-bs-target="#pointage" type="button" role="tab" aria-controls="pointage" aria-selected="true"> type="button" role="tab" aria-controls="pointage" aria-selected="false"> Pointage </button> <?php endif ?> <button class="nav-link" id="mails-tab" data-bs-toggle="tab" data-bs-target="#mails" type="button" role="tab" aria-controls="mails" aria-selected="true"> type="button" role="tab" aria-controls="mails" aria-selected="false"> Mails </button> </div> <!-- ONGLET :: PANE------------------------------------------------------------------------------------------------> <div class="tab-content"> <div id="inscriptions" class="tab-pane"> <!-- ONGLET :: PANE --> <div class="tab-content" id="nav-tabContent"> <div id="inscriptions" class="tab-pane show active" role="tabpanel" aria-labelledby="inscriptions-tab" tabindex="0"> <?php echo $this->partial('partial/inscription', ['evenement' => $evenement], [], null); ?> </div> <?php if ($canModifierInscription): ?> <div id="scan" class="tab-pane"> <div id="scan" class="tab-pane " role="tabpanel" aria-labelledby="scan-tab" tabindex="0"> <?php echo $this->partial('partial/scan', [ 'callbackUrl' => '/qr/callback', 'evenement' => $evenement ], [], null); ?> </div> <div id="pointage" class="tab-pane"> <div id="pointage" class="tab-pane " role="tabpanel" aria-labelledby="pointage-tab" tabindex="0"> <?php echo $this->partial('partial/pointage', ['evenement' => $evenement], [], null); ?> </div> <?php endif ?> <div id="mails" class="tab-pane"> <h2> Mails envoyés </h2> <div id="mails" class="tab-pane " role="tabpanel" aria-labelledby="mails-tab" tabindex="0"> <h2>Mails envoyés</h2> <?php echo $this->mails($mails); ?> </div> </div> <script type="module"> import { startQr, stopQr, initQr } from "/js/qr.js"; document.addEventListener('DOMContentLoaded', function () { function handleTabChange(e) { const targetSel = e.target.getAttribute('data-bs-target'); if (targetSel === '#scan') { // console.log('START QR'); initQr(); } else { // console.log('STOP QR'); stopQr(); } } // Bind event document.querySelectorAll('[data-bs-toggle="tab"]').forEach((tab) => { tab.addEventListener('shown.bs.tab', handleTabChange); }); // Cas où scan est actif au chargement if (document.querySelector('#scan.tab-pane.active')) { console.log('START QR'); initQr(); } }); </script> <script> $(function () { Loading module/Qr/view/qr/scan/index.phtml +5 −0 Changes for module/Qr/view/qr/scan/index.phtml: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -24,4 +24,9 @@ $callbackUrl = $this->callbackUrl ?? '/qr/callback'; <script type="module" src="/js/qr.js"></script> <script type="module"> import { initQr } from "/js/qr.js"; initQr(); </script> <link rel="stylesheet" href="/css/qr.css"> public/js/qr.js +28 −10 Changes for public/js/qr.js: 28 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -210,10 +210,11 @@ async function listCameras() { return videoInputs; } async function start(deviceId = null) { async function startQr(deviceId = null) { // console.log('Start QR'); // Stop propre avant de (re)lancer try { await stop(); await stopQr(); } catch { } Loading @@ -225,9 +226,21 @@ async function start(deviceId = null) { deviceId: deviceId ? {exact: deviceId} : undefined, width: {ideal: 1280}, height: {ideal: 720}, /* facing mode Sur mobile : 'user' = caméra frontale , 'environment' = caméra arrière sur desktop ignoré */ facingMode: {ideal: 'environment'}, /* Demande autofocus continu fonctionne surtout sur Android souvent ignoré sur desktop parfois ignoré sur iOS */ advanced: [{focusMode: 'continuous'}] }, // On ne demande pas le micro audio: false }; Loading Loading @@ -307,7 +320,8 @@ async function start(deviceId = null) { } } async function stop() { async function stopQr() { // console.log('Stop QR'); try { // 1) Arrête le décodage ZXing reader.reset(); // BrowserMultiFormatReader Loading Loading @@ -340,7 +354,8 @@ async function stop() { setStatus('Caméra arrêtée.'); } async function init() { async function initQr() { // console.log('Init QR'); if (!navigator.mediaDevices?.getUserMedia) { statusEl.textContent = 'getUserMedia non supporté par ce navigateur.'; return; Loading @@ -355,17 +370,17 @@ async function init() { if (cams.length) { selectEl.value = preferredId || cams[0].deviceId; await start(selectEl.value); await startQr(selectEl.value); } else { // Essaie sans deviceId (laisser le navigateur choisir) await start(null); await startQr(null); } btnStart?.addEventListener('click', () => start(selectEl?.value || undefined)); btnStop?.addEventListener('click', stop); btnStart?.addEventListener('click', () => startQr(selectEl?.value || undefined)); btnStop?.addEventListener('click', stopQr); btnPause?.addEventListener('click', () => setPaused(true)); btnResume?.addEventListener('click', () => setPaused(false)); selectEl?.addEventListener('change', () => start(selectEl.value)); selectEl?.addEventListener('change', () => startQr(selectEl.value)); unlockAudio(); } catch (e) { Loading @@ -373,4 +388,7 @@ async function init() { } } init(); // initialisation au demmarage // initQr(); export { startQr, stopQr, initQr }; No newline at end of file Loading
module/Evenementiel/view/evenementiel/evenement/afficher.phtml +51 −13 Changes for module/Evenementiel/view/evenementiel/evenement/afficher.phtml: 51 added lines, 13 removed lines. Original line number Diff line number Diff line Loading @@ -144,57 +144,95 @@ $canModifierInscription = $this->isAllowed(EvenementielinscriptionPrivileges::ge </div> </div> <!-- ONGLET :: TAB ------------------------------------------------------------------------------------------------> <!-- ONGLET :: TAB --> <div class="nav nav-tabs" id="nav-tab" role="tablist"> <button class="nav-link active" id="inscriptions-tab" data-bs-toggle="tab" data-bs-target="#inscriptions" type="button" role="tab" aria-controls="inscriptions" aria-selected="true"> Inscription et listes </button> <?php if ($canModifierInscription): ?> <button class="nav-link" id="scan-tab" data-bs-toggle="tab" data-bs-target="#scan" type="button" role="tab" aria-controls="scan" aria-selected="true"> type="button" role="tab" aria-controls="scan" aria-selected="false"> Scan </button> <button class="nav-link" id="pointage-tab" data-bs-toggle="tab" data-bs-target="#pointage" type="button" role="tab" aria-controls="pointage" aria-selected="true"> type="button" role="tab" aria-controls="pointage" aria-selected="false"> Pointage </button> <?php endif ?> <button class="nav-link" id="mails-tab" data-bs-toggle="tab" data-bs-target="#mails" type="button" role="tab" aria-controls="mails" aria-selected="true"> type="button" role="tab" aria-controls="mails" aria-selected="false"> Mails </button> </div> <!-- ONGLET :: PANE------------------------------------------------------------------------------------------------> <div class="tab-content"> <div id="inscriptions" class="tab-pane"> <!-- ONGLET :: PANE --> <div class="tab-content" id="nav-tabContent"> <div id="inscriptions" class="tab-pane show active" role="tabpanel" aria-labelledby="inscriptions-tab" tabindex="0"> <?php echo $this->partial('partial/inscription', ['evenement' => $evenement], [], null); ?> </div> <?php if ($canModifierInscription): ?> <div id="scan" class="tab-pane"> <div id="scan" class="tab-pane " role="tabpanel" aria-labelledby="scan-tab" tabindex="0"> <?php echo $this->partial('partial/scan', [ 'callbackUrl' => '/qr/callback', 'evenement' => $evenement ], [], null); ?> </div> <div id="pointage" class="tab-pane"> <div id="pointage" class="tab-pane " role="tabpanel" aria-labelledby="pointage-tab" tabindex="0"> <?php echo $this->partial('partial/pointage', ['evenement' => $evenement], [], null); ?> </div> <?php endif ?> <div id="mails" class="tab-pane"> <h2> Mails envoyés </h2> <div id="mails" class="tab-pane " role="tabpanel" aria-labelledby="mails-tab" tabindex="0"> <h2>Mails envoyés</h2> <?php echo $this->mails($mails); ?> </div> </div> <script type="module"> import { startQr, stopQr, initQr } from "/js/qr.js"; document.addEventListener('DOMContentLoaded', function () { function handleTabChange(e) { const targetSel = e.target.getAttribute('data-bs-target'); if (targetSel === '#scan') { // console.log('START QR'); initQr(); } else { // console.log('STOP QR'); stopQr(); } } // Bind event document.querySelectorAll('[data-bs-toggle="tab"]').forEach((tab) => { tab.addEventListener('shown.bs.tab', handleTabChange); }); // Cas où scan est actif au chargement if (document.querySelector('#scan.tab-pane.active')) { console.log('START QR'); initQr(); } }); </script> <script> $(function () { Loading
module/Qr/view/qr/scan/index.phtml +5 −0 Changes for module/Qr/view/qr/scan/index.phtml: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -24,4 +24,9 @@ $callbackUrl = $this->callbackUrl ?? '/qr/callback'; <script type="module" src="/js/qr.js"></script> <script type="module"> import { initQr } from "/js/qr.js"; initQr(); </script> <link rel="stylesheet" href="/css/qr.css">
public/js/qr.js +28 −10 Changes for public/js/qr.js: 28 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -210,10 +210,11 @@ async function listCameras() { return videoInputs; } async function start(deviceId = null) { async function startQr(deviceId = null) { // console.log('Start QR'); // Stop propre avant de (re)lancer try { await stop(); await stopQr(); } catch { } Loading @@ -225,9 +226,21 @@ async function start(deviceId = null) { deviceId: deviceId ? {exact: deviceId} : undefined, width: {ideal: 1280}, height: {ideal: 720}, /* facing mode Sur mobile : 'user' = caméra frontale , 'environment' = caméra arrière sur desktop ignoré */ facingMode: {ideal: 'environment'}, /* Demande autofocus continu fonctionne surtout sur Android souvent ignoré sur desktop parfois ignoré sur iOS */ advanced: [{focusMode: 'continuous'}] }, // On ne demande pas le micro audio: false }; Loading Loading @@ -307,7 +320,8 @@ async function start(deviceId = null) { } } async function stop() { async function stopQr() { // console.log('Stop QR'); try { // 1) Arrête le décodage ZXing reader.reset(); // BrowserMultiFormatReader Loading Loading @@ -340,7 +354,8 @@ async function stop() { setStatus('Caméra arrêtée.'); } async function init() { async function initQr() { // console.log('Init QR'); if (!navigator.mediaDevices?.getUserMedia) { statusEl.textContent = 'getUserMedia non supporté par ce navigateur.'; return; Loading @@ -355,17 +370,17 @@ async function init() { if (cams.length) { selectEl.value = preferredId || cams[0].deviceId; await start(selectEl.value); await startQr(selectEl.value); } else { // Essaie sans deviceId (laisser le navigateur choisir) await start(null); await startQr(null); } btnStart?.addEventListener('click', () => start(selectEl?.value || undefined)); btnStop?.addEventListener('click', stop); btnStart?.addEventListener('click', () => startQr(selectEl?.value || undefined)); btnStop?.addEventListener('click', stopQr); btnPause?.addEventListener('click', () => setPaused(true)); btnResume?.addEventListener('click', () => setPaused(false)); selectEl?.addEventListener('change', () => start(selectEl.value)); selectEl?.addEventListener('change', () => startQr(selectEl.value)); unlockAudio(); } catch (e) { Loading @@ -373,4 +388,7 @@ async function init() { } } init(); // initialisation au demmarage // initQr(); export { startQr, stopQr, initQr }; No newline at end of file