Paillasse/design/_backup-ludique/resources/views/bibliotheque.blade.php
2026-10-06 23:28:18 +02:00

96 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('layouts.vitrine')
@section('titre', 'Bibliothèque')
@section('contenu')
<section class="border-b-4 border-black bg-white">
<div class="mx-auto max-w-7xl px-5 pb-12 pt-12 lg:px-10">
<p class="inline-block -rotate-2 border-2 border-black bg-[#C4B5FD] px-3 py-1 text-sm font-extrabold uppercase tracking-wider shadow-[4px_4px_0px_#000000]">Bibliothèque du prof</p>
<h1 class="mt-6 max-w-5xl text-6xl font-black leading-[0.9] tracking-tighter sm:text-7xl">Tout le référentiel, fiche par fiche.</h1>
<p class="mt-6 max-w-3xl text-xl font-medium leading-relaxed">Du SNT au master, en passant par l’école d’ingénieurs. Chaque fiche regroupe cours, quiz, TD, labs et examens. Un même chapitre sert plusieurs formations : OSPF compte pour la NSI, le BTS SIO, le BTS CIEL, le BUT R&amp;T et les titres pro.</p>
<dl id="stats" class="mt-10 grid max-w-4xl grid-cols-2 border-4 border-black sm:grid-cols-5"></dl>
<div class="mt-6 max-w-4xl border-4 border-black bg-[#7CF2C0] p-4 text-sm font-bold shadow-[4px_4px_0px_#000000]"><p>Construit à partir des programmes officiels. Vérifié le 29 septembre 2026 :</p><ul class="mt-2 flex flex-wrap gap-x-5 gap-y-1 underline underline-offset-4"><li><a href="https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000049926463" target="_blank" rel="noopener">BTS SIO · arrêté du 8 juillet 2024 (épreuves E5, E6, E7)</a></li><li><a href="https://www.francecompetences.fr/recherche/rncp/37391/" target="_blank" rel="noopener">BTS CIEL · RNCP37391, arrêté du 25 janvier 2023</a></li><li><a href="https://www.onisep.fr/ressources/univers-formation/formations/post-bac/but-reseaux-et-telecommunications-parcours-cybersecurite" target="_blank" rel="noopener">BUT R&amp;T · 5 parcours (Onisep)</a></li></ul></div>
</div>
</section>
<div class="sticky top-0 z-20 border-b-4 border-black bg-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-center gap-3 px-5 py-3 lg:px-10">
<div class="flex border-4 border-black font-extrabold" role="tablist">
<button type="button" data-vue="themes" aria-selected="true" class="px-4 py-2 aria-selected:bg-black aria-selected:text-white">Par thème</button>
<button type="button" data-vue="formations" aria-selected="false" class="border-l-4 border-black px-4 py-2 aria-selected:bg-black aria-selected:text-white">Par formation</button>
<button type="button" data-vue="examens" aria-selected="false" class="border-l-4 border-black px-4 py-2 aria-selected:bg-black aria-selected:text-white">Examens</button>
</div>
<input id="b-recherche" class="min-w-[200px] flex-1 border-4 border-black px-3 py-2 font-semibold focus:bg-[#FFFBEA] focus:outline-none" placeholder="Rechercher : OSPF, chmod, RSA…" aria-label="Rechercher">
<select id="b-theme" class="border-4 border-black px-3 py-2 font-bold" aria-label="Thème"><option value="">Tous les thèmes</option></select>
<label class="flex items-center gap-2 font-bold"><input id="b-vm" type="checkbox" class="h-5 w-5 accent-black"> Masquer hors VM</label>
<p class="ml-auto border-4 border-black bg-[#7CF2C0] px-3 py-2 font-extrabold">Ma séquence : <span id="b-seq">0</span></p>
</div>
<div class="mx-auto flex max-w-7xl flex-wrap gap-2 px-5 pb-3 lg:px-10" role="group" aria-label="Activités">
<button type="button" data-tag="C" aria-pressed="false" class="border-2 border-black bg-white px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">C · Cours</button>
<button type="button" data-tag="Q" aria-pressed="false" class="border-2 border-black bg-[#FFD23F] px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">Q · Quiz</button>
<button type="button" data-tag="TD" aria-pressed="false" class="border-2 border-black bg-[#C4B5FD] px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">TD · TD</button>
<button type="button" data-tag="LAB" aria-pressed="false" class="border-2 border-black bg-[#7CF2C0] px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">LAB · TP sur VM</button>
<button type="button" data-tag="LAB+" aria-pressed="false" class="border-2 border-black bg-[#7CF2C0] px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">LAB+ · Lab multi-VM</button>
<button type="button" data-tag="IDE" aria-pressed="false" class="border-2 border-black bg-[#13233A] text-white px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">IDE · IDE</button>
<button type="button" data-tag="GEN" aria-pressed="false" class="border-2 border-black bg-[#FF6FB5] px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">GEN · Générateur</button>
<button type="button" data-tag="EXAM" aria-pressed="false" class="border-2 border-black bg-[#ec3013] text-white px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">EXAM · Examen</button>
<button type="button" data-tag="PROJ" aria-pressed="false" class="border-2 border-black bg-white px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">PROJ · Projet</button>
<button type="button" data-tag="CTF" aria-pressed="false" class="border-2 border-black bg-black text-white px-2 py-0.5 font-mono text-xs font-semibold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-1 aria-pressed:outline-black">CTF · CTF</button>
</div>
</div>
<div id="b-contenu" class="mx-auto max-w-7xl px-5 py-12 lg:px-10" data-url-cours="{{ route('cours.show') }}" data-url-ide="{{ route('ide') }}" data-url-lab="{{ route('labs.essai') }}" data-url-gen="{{ route('generateur') }}" data-url-exam="{{ route('examen') }}" data-url-banque="{{ route('banque') }}"></div>
<script src="{{ asset('js/referentiel.js') }}"></script>
<script>
(function () {
var R = window.REFERENTIEL, box = document.getElementById('b-contenu'), vue = 'themes', seq = 0, actifs = [];
var BG = {"C":"bg-white","Q":"bg-[#FFD23F]","TD":"bg-[#C4B5FD]","LAB":"bg-[#7CF2C0]","LAB+":"bg-[#7CF2C0]","IDE":"bg-[#13233A] text-white","GEN":"bg-[#FF6FB5]","EXAM":"bg-[#ec3013] text-white","PROJ":"bg-white","CTF":"bg-black text-white"}; BG.HV = 'bg-white border-dashed';
var U = box.dataset;
var esc = function (s) { return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;'); };
var badges = function (tags) { return tags.split(' ').map(function (t) { return '<span class="border-2 border-black ' + (BG[t] || 'bg-white') + ' px-1.5 font-mono text-[11px] font-semibold">' + (t === 'HV' ? 'hors VM' : t) + '</span>'; }).join(''); };
var lien = function (tags) { var t = tags.split(' '); return t.indexOf('IDE') > -1 ? U.urlIde : t.indexOf('GEN') > -1 ? U.urlGen : (t.indexOf('LAB') > -1 || t.indexOf('LAB+') > -1) ? U.urlLab : t.indexOf('EXAM') > -1 ? U.urlExam : U.urlCours; };
var tous = []; R.themes.forEach(function (th) { th.items.forEach(function (it, i) { tous.push({ code: th.code + '-' + (i + 1), theme: th.code, t: it[0], tags: it[1] }); }); });
var nb = function (tag) { return tous.filter(function (f) { return f.tags.split(' ').indexOf(tag) > -1; }).length; };
document.getElementById('stats').innerHTML = [['Fiches', tous.length, 'bg-white'], ['Quiz', nb('Q'), 'bg-[#FFD23F]'], ['Labs', nb('LAB') + nb('LAB+'), 'bg-[#7CF2C0]'], ['Formations', R.formations.length, 'bg-[#C4B5FD]'], ['Examens', R.examens.length + nb('EXAM'), 'bg-[#FF6FB5]']].map(function (s, i) { return '<div class="' + (i ? 'border-l-4 ' : '') + 'border-black ' + s[2] + ' p-4"><dt class="font-mono text-sm font-semibold">' + s[0] + '</dt><dd class="text-4xl font-black">' + s[1] + '</dd></div>'; }).join('');
var sel = document.getElementById('b-theme'); R.themes.forEach(function (th) { var o = document.createElement('option'); o.value = th.code; o.textContent = th.code + ' · ' + th.nom; sel.appendChild(o); });
function garde(t, tags) {
var q = document.getElementById('b-recherche').value.toLowerCase(), tg = tags.split(' ');
if (q && t.toLowerCase().indexOf(q) === -1) return false;
if (document.getElementById('b-vm').checked && tg.indexOf('HV') > -1) return false;
return actifs.every(function (a) { return tg.indexOf(a) > -1; });
}
function carte(code, t, tags, sous) {
return '<li class="flex flex-col gap-3 border-4 border-black bg-white p-4 shadow-[5px_5px_0px_#000000]"><div class="flex items-start justify-between gap-2"><span class="border-2 border-black bg-black px-1.5 font-mono text-xs font-semibold text-white">' + code + '</span>' + (sous ? '<span class="text-right text-xs font-bold">' + sous + '</span>' : '') + '</div><p class="flex-1 font-extrabold leading-snug">' + esc(t) + '</p><div class="flex flex-wrap gap-1">' + badges(tags) + '</div><div class="flex flex-wrap gap-2 border-t-2 border-black pt-3"><a href="' + lien(tags) + '" class="border-2 border-black bg-[#FFD23F] px-2 py-0.5 text-sm font-extrabold hover:bg-black hover:text-white">Ouvrir</a><button type="button" data-ajout class="border-2 border-black bg-white px-2 py-0.5 text-sm font-extrabold hover:bg-[#7CF2C0]">+ Séquence</button></div></li>';
}
function rendre() {
var h = '', th = sel.value;
if (vue === 'themes') {
R.themes.filter(function (x) { return !th || x.code === th; }).forEach(function (x) {
var its = x.items.map(function (it, i) { return [x.code + '-' + (i + 1), it[0], it[1]]; }).filter(function (it) { return garde(it[1], it[2]); });
if (!its.length) return;
h += '<section class="mb-14"><h2 class="flex flex-wrap items-baseline gap-3 text-3xl font-black tracking-tight"><span class="border-4 border-black bg-[#C4B5FD] px-2 font-mono text-2xl shadow-[4px_4px_0px_#000000]">' + x.code + '</span>' + esc(x.nom) + '<span class="font-mono text-base font-semibold">' + its.length + ' fiche(s)</span></h2><ul class="mt-6 grid gap-5 sm:grid-cols-2 lg:grid-cols-4">' + its.map(function (it) { return carte(it[0], it[1], it[2]); }).join('') + '</ul></section>';
});
} else if (vue === 'formations') {
var gr = {}; R.formations.forEach(function (f) { (gr[f.groupe] = gr[f.groupe] || []).push(f); });
Object.keys(gr).forEach(function (g) {
var bloc = gr[g].map(function (f) {
var ch = f.chapitres.filter(function (c) { return garde(c[0], c[1]); });
if (!ch.length) return '';
return '<details class="border-4 border-black bg-white shadow-[5px_5px_0px_#000000]" open><summary class="cursor-pointer border-b-4 border-black bg-[#7CF2C0] px-5 py-3 text-xl font-black">' + esc(f.nom) + ' <span class="font-mono text-sm font-semibold">· ' + ch.length + ' chapitre(s)</span></summary><ul class="divide-y-2 divide-black">' + ch.map(function (c, i) { return '<li class="flex flex-wrap items-center gap-3 px-5 py-3"><span class="font-mono text-sm font-semibold">' + (i + 1) + '</span><a href="' + lien(c[1]) + '" class="min-w-0 flex-1 font-bold hover:underline">' + esc(c[0]) + '</a><span class="flex flex-wrap gap-1">' + badges(c[1]) + '</span><button type="button" data-ajout class="border-2 border-black px-2 text-xs font-extrabold hover:bg-[#7CF2C0]">+ Séquence</button></li>'; }).join('') + '</ul></details>';
}).join('');
if (bloc) h += '<section class="mb-12"><h2 class="text-3xl font-black tracking-tight">' + esc(g) + '</h2><div class="mt-5 grid gap-6">' + bloc + '</div></section>';
});
} else {
var ex = R.examens.filter(function (e) { return garde(e[0] + ' ' + e[1], 'EXAM'); });
var ext = tous.filter(function (f) { return f.tags.split(' ').indexOf('EXAM') > -1 && garde(f.t, f.tags); });
h += '<section class="mb-12"><h2 class="text-3xl font-black tracking-tight">Épreuves et examens blancs</h2><ul class="mt-6 grid gap-5 sm:grid-cols-2 lg:grid-cols-3">' + ex.map(function (e) { return '<li class="border-4 border-black bg-white p-5 shadow-[5px_5px_0px_#000000]"><p class="font-mono text-sm font-semibold">⏱ ' + e[2] + '</p><p class="mt-2 text-xl font-black">' + esc(e[0]) + '</p><p class="mt-1 font-semibold">' + esc(e[1]) + '</p><div class="mt-4 flex gap-2"><a href="' + U.urlExam + '" class="border-2 border-black bg-[#ec3013] px-2 py-0.5 text-sm font-extrabold text-white">Aperçu</a><a href="' + U.urlBanque + '" class="border-2 border-black bg-white px-2 py-0.5 text-sm font-extrabold hover:bg-[#FFD23F]">Personnaliser</a></div></li>'; }).join('') + '</ul></section>';
h += '<section><h2 class="text-3xl font-black tracking-tight">Fiches avec mode examen</h2><ul class="mt-6 grid gap-5 sm:grid-cols-2 lg:grid-cols-4">' + ext.map(function (f) { return carte(f.code, f.t, f.tags); }).join('') + '</ul></section>';
}
box.innerHTML = h || '<p class="border-4 border-black bg-white p-6 text-xl font-black">Aucune fiche ne correspond à ces filtres.</p>';
}
box.addEventListener('click', function (e) { var b = e.target.closest('[data-ajout]'); if (!b || b.disabled) return; seq++; document.getElementById('b-seq').textContent = seq; b.textContent = 'Ajoutée ✓'; b.disabled = true; b.classList.add('bg-[#7CF2C0]'); });
document.querySelectorAll('[data-vue]').forEach(function (b) { b.addEventListener('click', function () { vue = b.dataset.vue; document.querySelectorAll('[data-vue]').forEach(function (x) { x.setAttribute('aria-selected', x === b); }); rendre(); }); });
document.querySelectorAll('[data-tag]').forEach(function (b) { b.addEventListener('click', function () { var on = b.getAttribute('aria-pressed') !== 'true'; b.setAttribute('aria-pressed', on); actifs = Array.prototype.filter.call(document.querySelectorAll('[data-tag]'), function (x) { return x.getAttribute('aria-pressed') === 'true'; }).map(function (x) { return x.dataset.tag; }); rendre(); }); });
['b-recherche', 'b-theme', 'b-vm'].forEach(function (id) { document.getElementById(id).addEventListener('input', rendre); document.getElementById(id).addEventListener('change', rendre); });
rendre();
})();
</script>
@endsection