<?php
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\SandboxExtension;
use Twig\Markup;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\Template;
use Twig\TemplateWrapper;
/* pages/listelivre.html.twig */
class __TwigTemplate_2a8fb7fa7eca9999182491f324d06712 extends Template
{
private Source $source;
/**
* @var array<string, Template>
*/
private array $macros = [];
public function __construct(Environment $env)
{
parent::__construct($env);
$this->source = $this->getSourceContext();
$this->blocks = [
'body' => [$this, 'block_body'],
'stylesheets' => [$this, 'block_stylesheets'],
'javascripts' => [$this, 'block_javascripts'],
];
}
protected function doGetParent(array $context): bool|string|Template|TemplateWrapper
{
// line 1
return "base.html.twig";
}
protected function doDisplay(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "pages/listelivre.html.twig"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "pages/listelivre.html.twig"));
$this->parent = $this->loadTemplate("base.html.twig", "pages/listelivre.html.twig", 1);
yield from $this->parent->unwrap()->yield($context, array_merge($this->blocks, $blocks));
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
}
// line 3
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_body(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
// line 4
yield "<div id=\"titleListe\">
";
// line 5
if ((array_key_exists("isSearchResult", $context) && (isset($context["isSearchResult"]) || array_key_exists("isSearchResult", $context) ? $context["isSearchResult"] : (function () { throw new RuntimeError('Variable "isSearchResult" does not exist.', 5, $this->source); })()))) {
// line 6
yield " <!-- Résultats de recherche avec formulaire de modification -->
<div class=\"card mb-4\">
<div class=\"card-header\" style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\">
<div class=\"d-flex justify-content-between align-items-center\">
<h5 class=\"mb-0 text-white\">
<i class=\"fas fa-search\"></i> Résultats de recherche
</h5>
";
// line 13
if (((isset($context["totalResults"]) || array_key_exists("totalResults", $context) ? $context["totalResults"] : (function () { throw new RuntimeError('Variable "totalResults" does not exist.', 13, $this->source); })()) > 0)) {
// line 14
yield " <span class=\"badge badge-light px-3 py-2\">";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape((isset($context["totalResults"]) || array_key_exists("totalResults", $context) ? $context["totalResults"] : (function () { throw new RuntimeError('Variable "totalResults" does not exist.', 14, $this->source); })()), "html", null, true);
yield " livre(s)</span>
";
}
// line 16
yield " </div>
</div>
<div class=\"card-body\">
<!-- Formulaire de recherche intégré -->
<form action=\"";
// line 20
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("searchBook");
yield "\" method=\"get\" class=\"mb-3\" id=\"searchForm\">
<div class=\"row\">
<div class=\"col-md-5 mb-2\">
<div class=\"input-group\">
<div class=\"input-group-prepend\">
<span class=\"input-group-text bg-white border-right-0\"><i class=\"fas fa-book text-primary\"></i></span>
</div>
<input type=\"text\" name=\"value\" class=\"form-control border-left-0\" id=\"search\"
value=\"";
// line 28
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape((isset($context["searchQuery"]) || array_key_exists("searchQuery", $context) ? $context["searchQuery"] : (function () { throw new RuntimeError('Variable "searchQuery" does not exist.', 28, $this->source); })()), "html", null, true);
yield "\"
placeholder=\"Titre, auteur ou ISBN...\">
<div class=\"input-group-append d-md-none\">
<button type=\"button\" class=\"btn bg-white border-left-0\" id=\"scanBarcodeBtn\" title=\"Scanner un code-barres\" style=\"border-color: #ced4da; color: #6c757d;\">
<i class=\"fas fa-barcode\"></i>
</button>
</div>
</div>
</div>
<div class=\"col-md-4 mb-2\">
<select name=\"user\" class=\"form-control\">
<option value=\"0\">Toutes les bibliothèques</option>
";
// line 40
if (array_key_exists("users", $context)) {
// line 41
yield " ";
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable((isset($context["users"]) || array_key_exists("users", $context) ? $context["users"] : (function () { throw new RuntimeError('Variable "users" does not exist.', 41, $this->source); })()));
foreach ($context['_seq'] as $context["_key"] => $context["user"]) {
// line 42
yield " <option value=\"";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["user"], "id", [], "any", false, false, false, 42), "html", null, true);
yield "\" ";
if ((array_key_exists("searchUserId", $context) && ((isset($context["searchUserId"]) || array_key_exists("searchUserId", $context) ? $context["searchUserId"] : (function () { throw new RuntimeError('Variable "searchUserId" does not exist.', 42, $this->source); })()) == CoreExtension::getAttribute($this->env, $this->source, $context["user"], "id", [], "any", false, false, false, 42)))) {
yield "selected";
}
yield ">
";
// line 43
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["user"], "name", [], "any", false, false, false, 43), "html", null, true);
yield " ";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["user"], "lastName", [], "any", false, false, false, 43), "html", null, true);
yield "
</option>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['user'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 46
yield " ";
}
// line 47
yield " </select>
</div>
<div class=\"col-md-3 mb-2\">
<button type=\"submit\" class=\"btn btn-primary btn-block\">
<i class=\"fas fa-search\"></i> Rechercher
</button>
</div>
</div>
</form>
<!-- Zone de scan de code-barres -->
<div id=\"barcodeScannerContainer\" class=\"mb-3\" style=\"display: none;\">
<div class=\"card border-primary\">
<div class=\"card-header bg-primary text-white d-flex justify-content-between align-items-center py-2\">
<span><i class=\"fas fa-camera\"></i> Scanner un code-barres ISBN</span>
<button type=\"button\" class=\"btn btn-sm btn-light\" id=\"closeScannerBtn\">
<i class=\"fas fa-times\"></i>
</button>
</div>
<div class=\"card-body p-0\">
<div id=\"barcodeReader\" style=\"width: 100%;\"></div>
<div class=\"p-2\">
<p class=\"text-muted small mb-0\">
<i class=\"fas fa-info-circle\"></i> Positionnez le code-barres ISBN devant la caméra.
</p>
</div>
</div>
</div>
</div>
<div class=\"d-flex flex-wrap align-items-center mb-3\">
<span class=\"mr-2 text-muted\">Recherche actuelle :</span>
<span class=\"badge badge-primary mr-2 px-3 py-2\" style=\"font-size: 0.95rem;\">";
// line 79
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape((isset($context["searchQuery"]) || array_key_exists("searchQuery", $context) ? $context["searchQuery"] : (function () { throw new RuntimeError('Variable "searchQuery" does not exist.', 79, $this->source); })()), "html", null, true);
yield "</span>
";
// line 80
if ((isset($context["searchUser"]) || array_key_exists("searchUser", $context) ? $context["searchUser"] : (function () { throw new RuntimeError('Variable "searchUser" does not exist.', 80, $this->source); })())) {
// line 81
yield " <span class=\"badge badge-success px-3 py-2\" style=\"font-size: 0.95rem;\">
<i class=\"fas fa-user\"></i> ";
// line 82
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape((isset($context["searchUser"]) || array_key_exists("searchUser", $context) ? $context["searchUser"] : (function () { throw new RuntimeError('Variable "searchUser" does not exist.', 82, $this->source); })()), "html", null, true);
yield "
</span>
";
}
// line 85
yield " </div>
";
// line 87
if (((isset($context["totalResults"]) || array_key_exists("totalResults", $context) ? $context["totalResults"] : (function () { throw new RuntimeError('Variable "totalResults" does not exist.', 87, $this->source); })()) == 0)) {
// line 88
yield " <div class=\"alert alert-warning border-0\" style=\"background-color: #fff3cd;\">
<h5 class=\"alert-heading\"><i class=\"fas fa-exclamation-triangle\"></i> Aucun résultat</h5>
<p class=\"mb-2\">Aucun livre ne correspond à \"<strong>";
// line 90
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape((isset($context["searchQuery"]) || array_key_exists("searchQuery", $context) ? $context["searchQuery"] : (function () { throw new RuntimeError('Variable "searchQuery" does not exist.', 90, $this->source); })()), "html", null, true);
yield "</strong>\"</p>
<hr>
<p class=\"mb-0 small\">
<strong>Suggestions :</strong> Vérifiez l'orthographe, essayez des termes plus généraux, ou vérifiez le code ISBN.
</p>
</div>
";
}
// line 97
yield "
<div class=\"d-flex flex-wrap\">
<a href=\"";
// line 99
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("listesLivres");
yield "\" class=\"btn btn-outline-secondary mb-2\">
<i class=\"fas fa-list\"></i> Tout le catalogue
</a>
</div>
</div>
</div>
";
} else {
// line 106
yield " <!-- Liste complète des livres -->
<div class=\"card mb-4\">
<div class=\"card-header\" style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\">
<div class=\"d-flex justify-content-between align-items-center\">
<h5 class=\"mb-0 text-white\">
<i class=\"fas fa-book\"></i> Catalogue complet
</h5>
<a href=\"";
// line 113
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("index");
yield "\" class=\"btn btn-light btn-sm\">
<i class=\"fas fa-search\"></i> Rechercher
</a>
</div>
</div>
<div class=\"card-body py-2\">
<small class=\"text-muted\">
<i class=\"fas fa-info-circle\"></i>
Cliquez sur une couverture pour l'agrandir, ou sur un titre pour voir les détails.
</small>
</div>
</div>
";
}
// line 126
yield "</div>
";
// line 128
if ((Twig\Extension\CoreExtension::length($this->env->getCharset(), (isset($context["Listelivres"]) || array_key_exists("Listelivres", $context) ? $context["Listelivres"] : (function () { throw new RuntimeError('Variable "Listelivres" does not exist.', 128, $this->source); })())) > 0)) {
// line 129
yield " ";
yield from $this->loadTemplate("includes/tableauLivres.html.twig", "pages/listelivre.html.twig", 129)->unwrap()->yield(CoreExtension::merge($context, ["pagination" => (isset($context["pagination"]) || array_key_exists("pagination", $context) ? $context["pagination"] : (function () { throw new RuntimeError('Variable "pagination" does not exist.', 129, $this->source); })()), "images" => (isset($context["images"]) || array_key_exists("images", $context) ? $context["images"] : (function () { throw new RuntimeError('Variable "images" does not exist.', 129, $this->source); })()), "Listelivres" => (isset($context["Listelivres"]) || array_key_exists("Listelivres", $context) ? $context["Listelivres"] : (function () { throw new RuntimeError('Variable "Listelivres" does not exist.', 129, $this->source); })())]));
}
// line 131
yield "
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 135
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_stylesheets(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
// line 136
yield " ";
yield from $this->yieldParentBlock("stylesheets", $context, $blocks);
yield "
<style>
/* Arrondir le bord droit de l'input sur desktop (quand le bouton scan est caché) */
@media (min-width: 768px) {
#search {
border-top-right-radius: 0.25rem !important;
border-bottom-right-radius: 0.25rem !important;
}
}
</style>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 148
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_javascripts(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
// line 149
yield " ";
yield from $this->yieldParentBlock("javascripts", $context, $blocks);
yield "
<!-- Bibliothèque html5-qrcode pour le scan de code-barres -->
<script src=\"https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js\"></script>
<script>
\$(document).ready(function () {
var modal = document.getElementById(\"myModal\");
var modalImg = document.getElementById(\"img01\");
var captionText = document.getElementById(\"caption\");
// Fermer la modale en cliquant sur le X
\$('.image-modal-close').click(function() {
modal.style.display = \"none\";
});
// Fermer la modale en cliquant sur le fond
\$('#myModal').click(function (event) {
if (event.target === modal) {
modal.style.display = \"none\";
}
});
// Ouvrir la modale en cliquant sur une image
\$('.img-cover').click(function (event) {
var image = document.getElementById(event.target.id);
modal.style.display = \"block\";
modalImg.src = image.src;
captionText.innerHTML = image.alt;
});
// Fermer avec Echap
\$(document).keydown(function(e) {
if (e.keyCode === 27) {
modal.style.display = \"none\";
}
});
// Scanner de code-barres
let html5QrCode = null;
let isScanning = false;
\$('#scanBarcodeBtn').click(function() {
\$('#barcodeScannerContainer').slideDown();
startScanner();
});
\$('#closeScannerBtn').click(function() {
stopScanner();
\$('#barcodeScannerContainer').slideUp();
});
function startScanner() {
if (isScanning) return;
html5QrCode = new Html5Qrcode(\"barcodeReader\");
const config = {
fps: 10,
qrbox: { width: 250, height: 100 },
formatsToSupport: [
Html5QrcodeSupportedFormats.EAN_13,
Html5QrcodeSupportedFormats.EAN_8,
Html5QrcodeSupportedFormats.UPC_A,
Html5QrcodeSupportedFormats.UPC_E,
Html5QrcodeSupportedFormats.CODE_128,
Html5QrcodeSupportedFormats.CODE_39
]
};
html5QrCode.start(
{ facingMode: \"environment\" },
config,
onScanSuccess,
onScanError
).then(() => {
isScanning = true;
}).catch((err) => {
console.error(\"Erreur démarrage scanner:\", err);
showScannerError(\"Impossible d'accéder à la caméra. Vérifiez les permissions.\");
});
}
function stopScanner() {
if (html5QrCode && isScanning) {
html5QrCode.stop().then(() => {
isScanning = false;
html5QrCode.clear();
}).catch((err) => {
console.error(\"Erreur arrêt scanner:\", err);
});
}
}
function onScanSuccess(decodedText, decodedResult) {
try {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
oscillator.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.1);
} catch(e) {}
\$('#search').val(decodedText);
showScannerSuccess(\"Code-barres détecté : \" + decodedText);
stopScanner();
setTimeout(function() {
\$('#barcodeScannerContainer').slideUp();
}, 1000);
}
function onScanError(errorMessage) {}
function showScannerSuccess(message) {
const alertHtml = '<div class=\"alert alert-success alert-dismissible fade show m-3\" role=\"alert\">' +
'<i class=\"fas fa-check-circle\"></i> ' + message +
'<button type=\"button\" class=\"close\" data-dismiss=\"alert\"><span>×</span></button>' +
'</div>';
\$('#barcodeReader').after(alertHtml);
}
function showScannerError(message) {
const alertHtml = '<div class=\"alert alert-danger m-3\" role=\"alert\">' +
'<i class=\"fas fa-exclamation-triangle\"></i> ' + message +
'</div>';
\$('#barcodeReader').html(alertHtml);
}
});
</script>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
/**
* @codeCoverageIgnore
*/
public function getTemplateName(): string
{
return "pages/listelivre.html.twig";
}
/**
* @codeCoverageIgnore
*/
public function isTraitable(): bool
{
return false;
}
/**
* @codeCoverageIgnore
*/
public function getDebugInfo(): array
{
return array ( 341 => 149, 328 => 148, 305 => 136, 292 => 135, 280 => 131, 276 => 129, 274 => 128, 270 => 126, 254 => 113, 245 => 106, 235 => 99, 231 => 97, 221 => 90, 217 => 88, 215 => 87, 211 => 85, 205 => 82, 202 => 81, 200 => 80, 196 => 79, 162 => 47, 159 => 46, 148 => 43, 139 => 42, 134 => 41, 132 => 40, 117 => 28, 106 => 20, 100 => 16, 94 => 14, 92 => 13, 83 => 6, 81 => 5, 78 => 4, 65 => 3, 42 => 1,);
}
public function getSourceContext(): Source
{
return new Source("{% extends 'base.html.twig' %}
{% block body %}
<div id=\"titleListe\">
{% if isSearchResult is defined and isSearchResult %}
<!-- Résultats de recherche avec formulaire de modification -->
<div class=\"card mb-4\">
<div class=\"card-header\" style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\">
<div class=\"d-flex justify-content-between align-items-center\">
<h5 class=\"mb-0 text-white\">
<i class=\"fas fa-search\"></i> Résultats de recherche
</h5>
{% if totalResults > 0 %}
<span class=\"badge badge-light px-3 py-2\">{{ totalResults }} livre(s)</span>
{% endif %}
</div>
</div>
<div class=\"card-body\">
<!-- Formulaire de recherche intégré -->
<form action=\"{{ path('searchBook') }}\" method=\"get\" class=\"mb-3\" id=\"searchForm\">
<div class=\"row\">
<div class=\"col-md-5 mb-2\">
<div class=\"input-group\">
<div class=\"input-group-prepend\">
<span class=\"input-group-text bg-white border-right-0\"><i class=\"fas fa-book text-primary\"></i></span>
</div>
<input type=\"text\" name=\"value\" class=\"form-control border-left-0\" id=\"search\"
value=\"{{ searchQuery }}\"
placeholder=\"Titre, auteur ou ISBN...\">
<div class=\"input-group-append d-md-none\">
<button type=\"button\" class=\"btn bg-white border-left-0\" id=\"scanBarcodeBtn\" title=\"Scanner un code-barres\" style=\"border-color: #ced4da; color: #6c757d;\">
<i class=\"fas fa-barcode\"></i>
</button>
</div>
</div>
</div>
<div class=\"col-md-4 mb-2\">
<select name=\"user\" class=\"form-control\">
<option value=\"0\">Toutes les bibliothèques</option>
{% if users is defined %}
{% for user in users %}
<option value=\"{{ user.id }}\" {% if searchUserId is defined and searchUserId == user.id %}selected{% endif %}>
{{ user.name }} {{ user.lastName }}
</option>
{% endfor %}
{% endif %}
</select>
</div>
<div class=\"col-md-3 mb-2\">
<button type=\"submit\" class=\"btn btn-primary btn-block\">
<i class=\"fas fa-search\"></i> Rechercher
</button>
</div>
</div>
</form>
<!-- Zone de scan de code-barres -->
<div id=\"barcodeScannerContainer\" class=\"mb-3\" style=\"display: none;\">
<div class=\"card border-primary\">
<div class=\"card-header bg-primary text-white d-flex justify-content-between align-items-center py-2\">
<span><i class=\"fas fa-camera\"></i> Scanner un code-barres ISBN</span>
<button type=\"button\" class=\"btn btn-sm btn-light\" id=\"closeScannerBtn\">
<i class=\"fas fa-times\"></i>
</button>
</div>
<div class=\"card-body p-0\">
<div id=\"barcodeReader\" style=\"width: 100%;\"></div>
<div class=\"p-2\">
<p class=\"text-muted small mb-0\">
<i class=\"fas fa-info-circle\"></i> Positionnez le code-barres ISBN devant la caméra.
</p>
</div>
</div>
</div>
</div>
<div class=\"d-flex flex-wrap align-items-center mb-3\">
<span class=\"mr-2 text-muted\">Recherche actuelle :</span>
<span class=\"badge badge-primary mr-2 px-3 py-2\" style=\"font-size: 0.95rem;\">{{ searchQuery }}</span>
{% if searchUser %}
<span class=\"badge badge-success px-3 py-2\" style=\"font-size: 0.95rem;\">
<i class=\"fas fa-user\"></i> {{ searchUser }}
</span>
{% endif %}
</div>
{% if totalResults == 0 %}
<div class=\"alert alert-warning border-0\" style=\"background-color: #fff3cd;\">
<h5 class=\"alert-heading\"><i class=\"fas fa-exclamation-triangle\"></i> Aucun résultat</h5>
<p class=\"mb-2\">Aucun livre ne correspond à \"<strong>{{ searchQuery }}</strong>\"</p>
<hr>
<p class=\"mb-0 small\">
<strong>Suggestions :</strong> Vérifiez l'orthographe, essayez des termes plus généraux, ou vérifiez le code ISBN.
</p>
</div>
{% endif %}
<div class=\"d-flex flex-wrap\">
<a href=\"{{ path('listesLivres') }}\" class=\"btn btn-outline-secondary mb-2\">
<i class=\"fas fa-list\"></i> Tout le catalogue
</a>
</div>
</div>
</div>
{% else %}
<!-- Liste complète des livres -->
<div class=\"card mb-4\">
<div class=\"card-header\" style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\">
<div class=\"d-flex justify-content-between align-items-center\">
<h5 class=\"mb-0 text-white\">
<i class=\"fas fa-book\"></i> Catalogue complet
</h5>
<a href=\"{{ path('index') }}\" class=\"btn btn-light btn-sm\">
<i class=\"fas fa-search\"></i> Rechercher
</a>
</div>
</div>
<div class=\"card-body py-2\">
<small class=\"text-muted\">
<i class=\"fas fa-info-circle\"></i>
Cliquez sur une couverture pour l'agrandir, ou sur un titre pour voir les détails.
</small>
</div>
</div>
{% endif %}
</div>
{% if Listelivres|length > 0 %}
{% include 'includes/tableauLivres.html.twig' with {'pagination' : pagination, 'images' : images, 'Listelivres' : Listelivres}%}
{% endif %}
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<style>
/* Arrondir le bord droit de l'input sur desktop (quand le bouton scan est caché) */
@media (min-width: 768px) {
#search {
border-top-right-radius: 0.25rem !important;
border-bottom-right-radius: 0.25rem !important;
}
}
</style>
{% endblock %}
{% block javascripts %}
{{parent()}}
<!-- Bibliothèque html5-qrcode pour le scan de code-barres -->
<script src=\"https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js\"></script>
<script>
\$(document).ready(function () {
var modal = document.getElementById(\"myModal\");
var modalImg = document.getElementById(\"img01\");
var captionText = document.getElementById(\"caption\");
// Fermer la modale en cliquant sur le X
\$('.image-modal-close').click(function() {
modal.style.display = \"none\";
});
// Fermer la modale en cliquant sur le fond
\$('#myModal').click(function (event) {
if (event.target === modal) {
modal.style.display = \"none\";
}
});
// Ouvrir la modale en cliquant sur une image
\$('.img-cover').click(function (event) {
var image = document.getElementById(event.target.id);
modal.style.display = \"block\";
modalImg.src = image.src;
captionText.innerHTML = image.alt;
});
// Fermer avec Echap
\$(document).keydown(function(e) {
if (e.keyCode === 27) {
modal.style.display = \"none\";
}
});
// Scanner de code-barres
let html5QrCode = null;
let isScanning = false;
\$('#scanBarcodeBtn').click(function() {
\$('#barcodeScannerContainer').slideDown();
startScanner();
});
\$('#closeScannerBtn').click(function() {
stopScanner();
\$('#barcodeScannerContainer').slideUp();
});
function startScanner() {
if (isScanning) return;
html5QrCode = new Html5Qrcode(\"barcodeReader\");
const config = {
fps: 10,
qrbox: { width: 250, height: 100 },
formatsToSupport: [
Html5QrcodeSupportedFormats.EAN_13,
Html5QrcodeSupportedFormats.EAN_8,
Html5QrcodeSupportedFormats.UPC_A,
Html5QrcodeSupportedFormats.UPC_E,
Html5QrcodeSupportedFormats.CODE_128,
Html5QrcodeSupportedFormats.CODE_39
]
};
html5QrCode.start(
{ facingMode: \"environment\" },
config,
onScanSuccess,
onScanError
).then(() => {
isScanning = true;
}).catch((err) => {
console.error(\"Erreur démarrage scanner:\", err);
showScannerError(\"Impossible d'accéder à la caméra. Vérifiez les permissions.\");
});
}
function stopScanner() {
if (html5QrCode && isScanning) {
html5QrCode.stop().then(() => {
isScanning = false;
html5QrCode.clear();
}).catch((err) => {
console.error(\"Erreur arrêt scanner:\", err);
});
}
}
function onScanSuccess(decodedText, decodedResult) {
try {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
oscillator.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.1);
} catch(e) {}
\$('#search').val(decodedText);
showScannerSuccess(\"Code-barres détecté : \" + decodedText);
stopScanner();
setTimeout(function() {
\$('#barcodeScannerContainer').slideUp();
}, 1000);
}
function onScanError(errorMessage) {}
function showScannerSuccess(message) {
const alertHtml = '<div class=\"alert alert-success alert-dismissible fade show m-3\" role=\"alert\">' +
'<i class=\"fas fa-check-circle\"></i> ' + message +
'<button type=\"button\" class=\"close\" data-dismiss=\"alert\"><span>×</span></button>' +
'</div>';
\$('#barcodeReader').after(alertHtml);
}
function showScannerError(message) {
const alertHtml = '<div class=\"alert alert-danger m-3\" role=\"alert\">' +
'<i class=\"fas fa-exclamation-triangle\"></i> ' + message +
'</div>';
\$('#barcodeReader').html(alertHtml);
}
});
</script>
{% endblock %}", "pages/listelivre.html.twig", "/home/jla23/project/DEV/Bdd-Books-DEV/templates/pages/listelivre.html.twig");
}
}