ajoute le portail Laravel : connexion prof/élève, session unique, gestion de classe, salle d'attente

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-10-08 02:01:58 +02:00
parent aa31b6112f
commit 30e14b1c54
191 changed files with 25324 additions and 0 deletions

View file

@ -0,0 +1,9 @@
@import 'tailwindcss';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
}

View file

@ -0,0 +1 @@
//

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,31 @@
@extends('layouts.vitrine')
@section('titre', 'Se connecter')
@section('contenu')
<section class="relative overflow-hidden">
<div aria-hidden="true" class="pointer-events-none absolute inset-0"></div>
<div class="relative mx-auto max-w-5xl px-5 pb-28 pt-24 lg:px-10">
<h1 style="margin:0;text-align:center;font-size:clamp(40px,6vw,64px);line-height:1.05;font-weight:800;letter-spacing:-0.03em;color:#0b1220">Se connecter.</h1>
<div class="mt-12 grid gap-10 lg:grid-cols-2">
<form action="{{ route('connexion.eleve') }}" method="post" class="grid content-start gap-5 p-8" style="border:1px solid #e3e5e8;border-radius:24px;background:#fff">
@csrf
<h2 style="margin:0;font-size:24px;font-weight:800;color:#0b1220">Je suis élève</h2>
@error('identifiant')<p class="font-bold text-[#A63D2A]">{{ $message }}</p>@enderror
<label class="grid gap-2 font-extrabold">Identifiant<input name="identifiant" value="{{ old('identifiant') }}" autocomplete="username" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30 font-mono" placeholder="lea.m.2nde-b"></label>
<label class="grid gap-2 font-extrabold">Code secret<input type="password" name="code" autocomplete="current-password" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30 font-mono"></label>
<p class="font-medium">Ils sont sur ta fiche de connexion. Tu peux aussi scanner le QR.</p>
<div><button type="submit" style="display:inline-flex;align-items:center;gap:10px;height:52px;padding:0 28px;border:0;border-radius:999px;background:#0b57d0;color:#fff;font-size:16px;font-weight:700;cursor:pointer">Entrer <span class="font-mono" aria-hidden="true">→</span></button></div>
</form>
<form action="{{ route('connexion.prof') }}" method="post" class="grid content-start gap-5 p-8" style="border:1px solid #e3e5e8;border-radius:24px;background:#fff">
@csrf
<h2 style="margin:0;font-size:24px;font-weight:800;color:#0b1220">Je suis enseignant</h2>
@error('email')<p class="font-bold text-[#A63D2A]">{{ $message }}</p>@enderror
<label class="grid gap-2 font-extrabold">E-mail<input type="email" name="email" value="{{ old('email') }}" autocomplete="email" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<label class="grid gap-2 font-extrabold">Mot de passe<input type="password" name="password" autocomplete="current-password" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<div class="flex flex-wrap items-center gap-5"><button type="submit" style="display:inline-flex;align-items:center;gap:10px;height:52px;padding:0 28px;border:0;border-radius:999px;background:#0b57d0;color:#fff;font-size:16px;font-weight:700;cursor:pointer">Se connecter</button><a href="{{ route('register') }}" class="font-extrabold underline underline-offset-4">Créer une classe</a></div>
</form>
</div>
</div>
</section>
@endsection

View file

@ -0,0 +1,68 @@
@extends('layouts.vitrine')
@section('titre', 'Créer une classe')
@section('contenu')
<section class="relative overflow-hidden">
<div aria-hidden="true" class="pointer-events-none absolute inset-0"><span class="flotte absolute left-[40%] bottom-10 h-9 w-9 rounded-full border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] [animation-delay:1.5s]"></span></div>
<div class="relative mx-auto grid max-w-7xl gap-12 px-5 pb-24 pt-16 lg:grid-cols-12 lg:px-10">
<div class="lg:col-span-5">
<p class="inline-block border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-3 py-1 text-sm font-bold">Enseignants</p>
<h1 class="mt-8 text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Créer une classe.</h1>
<p class="mt-6 inline-block border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] px-4 py-2 text-2xl font-extrabold">Gratuit · sans CB</p>
<p class="mt-8 text-xl font-medium">Ensuite, ajoutez vos élèves par code de classe, import CSV ou saisie rapide. Pour les mineurs, on ne demande que le nom, le prénom et le groupe.</p>
</div>
<form action="{{ route('inscription.store') }}" method="post" class="grid gap-5 border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-7 sm:grid-cols-2 lg:col-span-7">
@csrf
@if ($errors->any())
<div class="sm:col-span-2 font-bold text-[#A63D2A]">
<ul>@foreach ($errors->all() as $erreur)<li>{{ $erreur }}</li>@endforeach</ul>
</div>
@endif
<label class="grid gap-2 font-extrabold">Prénom<input name="prenom" value="{{ old('prenom') }}" autocomplete="given-name" required class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<label class="grid gap-2 font-extrabold">Nom<input name="nom" value="{{ old('nom') }}" autocomplete="family-name" required class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<label class="grid gap-2 font-extrabold sm:col-span-2">E-mail professionnel<input type="email" name="email" value="{{ old('email') }}" autocomplete="email" required class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<label class="grid gap-2 font-extrabold">Mot de passe<input type="password" name="password" autocomplete="new-password" required minlength="8" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<label class="grid gap-2 font-extrabold">Confirme le mot de passe<input type="password" name="password_confirmation" autocomplete="new-password" required minlength="8" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<div class="sm:col-span-2"><div class="grid gap-4">
<label class="grid gap-2 font-extrabold" for="etab-inscription">Établissement</label>
<select id="etab-inscription" name="etablissement_nom_liste" required data-etab class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30 -mt-2">
<option value="">Choisir dans la liste</option>
<optgroup label="Lycées"><option value="Lycée Jean-Jaurès · Montreuil">Lycée Jean-Jaurès · Montreuil</option><option value="Lycée Louis-Armand · Paris 15e">Lycée Louis-Armand · Paris 15e</option><option value="Lycée Gustave-Eiffel · Bordeaux">Lycée Gustave-Eiffel · Bordeaux</option><option value="Lycée La Martinière Monplaisir · Lyon">Lycée La Martinière Monplaisir · Lyon</option></optgroup>
<optgroup label="BTS et IUT"><option value="Lycée Saint-Exupéry · Marseille">Lycée Saint-Exupéry · Marseille</option><option value="IUT de Villetaneuse · R&amp;T">IUT de Villetaneuse · R&amp;T</option><option value="IUT de Lannion · R&amp;T">IUT de Lannion · R&amp;T</option></optgroup>
<optgroup label="Organismes de formation"><option value="Télécom Saint-Étienne · école d’ingénieurs">Télécom Saint-Étienne · école d’ingénieurs</option><option value="AFPA · Centre de Rennes">AFPA · Centre de Rennes</option></optgroup>
<option value="autre">Mon établissement n’est pas dans la liste</option>
</select>
<div data-etab-autre hidden class="relative grid gap-4 border border-[#e3e5e8] rounded-2xl bg-white p-5">
<span class="absolute -right-3 -top-4 border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-3 py-1 text-sm font-extrabold">Gratuit · sans CB</span>
<p class="font-semibold">C’est avec grand plaisir qu’on vous laisse l’accès, sans carte bancaire. En échange, donnez-nous un coup de pouce : aidez-nous à faire souscrire une offre à votre établissement, ou envoyez-nous vos critiques et remarques pour rendre l’outil plus utile.</p>
<label class="grid gap-2 font-extrabold">Nom de l’établissement<input name="etablissement_nom" data-req class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30" placeholder="Lycée Marie-Curie"></label>
<div class="grid gap-4 sm:grid-cols-2">
<label class="grid gap-2 font-extrabold">Ville<input name="etablissement_ville" data-req class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"></label>
<label class="grid gap-2 font-extrabold">Code UAI <span class="font-semibold">(facultatif)</span><input name="etablissement_uai" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30 font-mono" placeholder="0931234A"></label>
</div>
<fieldset class="grid gap-2 font-semibold">
<legend class="font-extrabold">Mon coup de pouce</legend>
<label class="flex items-center gap-3"><input type="checkbox" name="aide[]" value="offre" class="h-5 w-5 accent-black"> Aider à faire souscrire une offre</label>
<label class="flex items-center gap-3"><input type="checkbox" name="aide[]" value="avis" class="h-5 w-5 accent-black"> Envoyer mes critiques et remarques</label>
</fieldset>
</div>
</div></div>
<label class="grid gap-2 font-extrabold">Formation<select name="formation" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30"><option>Lycée NSI</option><option>BTS SIO SISR</option><option>BTS CIEL</option><option>BUT R&amp;T</option><option>Titre pro TSSR</option></select></label>
<label class="grid gap-2 font-extrabold">Nom de la classe<input name="classe" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-4 py-3 text-base font-semibold text-black placeholder:text-[#5f6368] focus:border-[#0b57d0] focus:outline-none focus:ring-2 focus:ring-[#0b57d0]/30" placeholder="2nde NSI · Groupe B"></label>
<div class="sm:col-span-2"><button type="submit" style="display:inline-flex;align-items:center;gap:10px;height:52px;padding:0 28px;border:0;border-radius:999px;background:#0b57d0;color:#fff;font-size:16px;font-weight:700;cursor:pointer">Créer la classe <span class="font-mono" aria-hidden="true">→</span></button>
<p class="mt-3 font-semibold">Aucune carte bancaire demandée.</p></div>
</form>
</div>
</section>
<script>
document.querySelectorAll('[data-etab]').forEach(function (s) {
var box = s.parentNode.querySelector('[data-etab-autre]');
function maj() {
box.hidden = s.value !== 'autre';
box.querySelectorAll('[data-req]').forEach(function (i) { i.required = !box.hidden; });
}
s.addEventListener('change', maj); maj();
});
</script>
@endsection

View file

@ -0,0 +1,185 @@
@extends('layouts.vitrine')
@section('titre', 'Banque de sujets')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-end gap-6 px-5 pb-10 pt-10 lg:px-10">
<div class="flex-1">
<p class="font-mono text-sm font-semibold">Espace enseignant · Banque</p>
<div class="min-w-0 flex-1"><p data-public="P" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#1d3fa8]">Pour les profs</p>
<h1 class="mt-2 text-5xl font-extrabold leading-[0.95] tracking-tight sm:text-6xl">Banque de sujets et de questions</h1></div>
<p class="mt-3 max-w-2xl text-lg font-semibold">1 240 questions classées par cursus et par notion. Modifiez-les, ajoutez les vôtres, composez vos sujets.</p><div class="mt-4 flex flex-wrap gap-3"><a href="{{ route('bibliotheque') }}" class="border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2 font-extrabold hover:bg-[#fef7e0]">Bibliothèque du référentiel →</a><a href="{{ route('generateur') }}" class="border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] px-4 py-2 font-extrabold">Générateur de TD →</a></div>
</div>
<a href="#editeur" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013] disabled:cursor-not-allowed disabled:bg-[#444141] disabled:shadow-none">+ Nouvelle question</a>
</div>
</section>
<section id="flash" class="scroll-mt-6 border-b border-[#e3e5e8] bg-[#fef7e0]" aria-labelledby="t-flash">
<div class="mx-auto grid max-w-7xl gap-10 px-5 py-14 lg:grid-cols-12 lg:px-10">
<div class="lg:col-span-4">
<p class="inline-block border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-bold">Début d’heure</p>
<h2 id="t-flash" class="mt-5 text-4xl font-extrabold leading-tight tracking-tight">Un quiz flash pour lancer le cours.</h2>
<p class="mt-4 text-lg font-semibold">Choisissez les outils à réviser. Syllabus tire les questions dans la banque. Un diaporama s’ouvre au tableau. Les élèves se connectent avec leur identifiant depuis leur téléphone ou leur PC, et vous voyez tout de suite qui manque.</p>
<span class="mt-4 flex flex-wrap gap-4"><a href="{{ route('quiz.projection') }}" class="font-extrabold underline underline-offset-4">Voir le diaporama →</a><a href="{{ route('quiz.eleve') }}" class="font-extrabold underline underline-offset-4">Voir la vue élève →</a></span>
</div>
<div class="border border-[#e3e5e8] rounded-2xl bg-white p-6 lg:col-span-8">
<p class="font-extrabold">Outils à réviser</p>
<div class="mt-3 flex flex-wrap gap-2" role="group" aria-label="Outils">
<button type="button" data-outil aria-pressed="true" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">ls</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">cd</button>
<button type="button" data-outil aria-pressed="true" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">chmod</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">chown</button>
<button type="button" data-outil aria-pressed="true" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">grep</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">find</button>
<button type="button" data-outil aria-pressed="true" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">ip</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">ping</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">ss</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">dig</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">ssh</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">systemctl</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">apt</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">journalctl</button>
<button type="button" data-outil aria-pressed="false" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono font-semibold aria-pressed:bg-black aria-pressed:text-white">tar</button>
</div>
<div class="mt-5 grid gap-4 sm:grid-cols-3">
<label class="grid gap-2 font-extrabold">Questions<select id="flash-n" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>5</option><option>8</option><option>10</option></select></label>
<label class="grid gap-2 font-extrabold">Durée<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>5 min</option><option>8 min</option><option>10 min</option></select></label>
<label class="grid gap-2 font-extrabold">Classe<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>BTS SIO 1 · Groupe A</option><option>2nde NSI · Groupe B</option></select></label>
</div>
<div class="mt-6 flex flex-wrap items-center gap-5">
<button type="button" id="flash-go" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013] disabled:cursor-not-allowed disabled:bg-[#444141] disabled:shadow-none">Lancer le diaporama →</button>
<p id="flash-res" hidden class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-4 py-2 font-extrabold" aria-live="polite"></p>
</div>
</div>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-10 px-5 py-12 lg:grid-cols-12 lg:px-10">
<aside class="grid content-start gap-5 lg:col-span-3" aria-label="Filtres">
<label class="grid gap-2 font-extrabold">Rechercher<input id="recherche" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none" placeholder="masque, VLAN…"></label>
<label class="grid gap-2 font-extrabold">Cursus<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>Tous</option><option>NSI</option><option>BTS SIO</option><option>BTS CIEL</option><option>BUT R&amp;T</option><option>TSSR</option></select></label>
<label class="grid gap-2 font-extrabold">Type<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>Tous</option><option>Choix unique</option><option>Choix multiple</option><option>Vrai / faux</option><option>Réponse numérique</option><option>Réponse courte</option><option>Texte à trous</option></select></label>
<label class="grid gap-2 font-extrabold">Difficulté<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>Toutes</option><option>Facile</option><option>Moyen</option><option>Difficile</option></select></label>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-4">
<p class="font-extrabold">Sujets prêts</p>
<ul class="mt-3 grid gap-2"><li class="border border-[#dadce0] rounded-lg bg-[#fef7e0] p-2"><p class="font-bold leading-tight">E6 blanc SISR · Adressage et VLAN</p><p class="font-mono text-xs font-semibold">12 questions + TP · 1 h</p></li><li class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] p-2"><p class="font-bold leading-tight">QCM Bloc 2 · fin de trimestre</p><p class="font-mono text-xs font-semibold">20 questions · 40 min</p></li><li class="border border-[#dadce0] rounded-lg bg-[#eef0fd] p-2"><p class="font-bold leading-tight">Contrôle NSI · Architectures</p><p class="font-mono text-xs font-semibold">10 questions · 30 min</p></li></ul>
</div>
</aside>
<section class="lg:col-span-5" aria-labelledby="t-questions">
<h2 id="t-questions" class="text-2xl font-extrabold">Questions <span class="font-mono text-base font-semibold">· 7 affichées sur 1 240</span></h2>
<ul id="liste-questions" class="mt-5 grid gap-5">
<li data-question data-pts="2" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Choix unique</span><span class="border border-[#dadce0] rounded-lg px-2">BTS SIO · Bloc 2</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">Adressage IPv4</span><span class="border border-[#dadce0] rounded-lg bg-[#eef0fd] px-2">Moyen</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Quelle est l’adresse réseau de 10.0.3.200/22 ?</p>
<p class="mt-2 font-mono text-xs font-semibold">2 pts · utilisée 34 fois · réussite 38 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
<li data-question data-pts="1" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Choix unique</span><span class="border border-[#dadce0] rounded-lg px-2">BTS CIEL · Réseaux</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">Adressage IPv4</span><span class="border border-[#dadce0] rounded-lg bg-white px-2">Facile</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Combien d’hôtes utilisables dans un /27 ?</p>
<p class="mt-2 font-mono text-xs font-semibold">1 pt · utilisée 51 fois · réussite 71 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
<li data-question data-pts="1" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Choix multiple</span><span class="border border-[#dadce0] rounded-lg px-2">NSI · Première</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">Commandes Linux</span><span class="border border-[#dadce0] rounded-lg bg-white px-2">Facile</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Quelles commandes affichent les interfaces réseau sous Debian ?</p>
<p class="mt-2 font-mono text-xs font-semibold">1 pt · utilisée 22 fois · réussite 64 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
<li data-question data-pts="1" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Vrai / faux</span><span class="border border-[#dadce0] rounded-lg px-2">BTS SIO · Bloc 2</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">VLAN</span><span class="border border-[#dadce0] rounded-lg bg-white px-2">Facile</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Un VLAN isole le trafic au niveau 2 du modèle OSI.</p>
<p class="mt-2 font-mono text-xs font-semibold">1 pt · utilisée 40 fois · réussite 82 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
<li data-question data-pts="2" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Réponse courte</span><span class="border border-[#dadce0] rounded-lg px-2">BTS SIO · Bloc 1</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">Droits Linux</span><span class="border border-[#dadce0] rounded-lg bg-[#eef0fd] px-2">Moyen</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Écrivez la commande qui donne les droits rwxr-x--- au fichier notes.txt.</p>
<p class="mt-2 font-mono text-xs font-semibold">2 pts · utilisée 18 fois · réussite 47 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
<li data-question data-pts="1" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Réponse numérique</span><span class="border border-[#dadce0] rounded-lg px-2">BUT R&amp;T · S1</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">Services réseau</span><span class="border border-[#dadce0] rounded-lg bg-white px-2">Facile</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Quel port utilise par défaut le protocole SSH ?</p>
<p class="mt-2 font-mono text-xs font-semibold">1 pt · utilisée 29 fois · réussite 88 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
<li data-question data-pts="3" class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<div class="flex flex-wrap gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">Texte à trous</span><span class="border border-[#dadce0] rounded-lg px-2">BTS CIEL · Réseaux</span><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">Routage</span><span class="border border-[#dadce0] rounded-lg bg-[#ec3013] text-white px-2">Difficile</span></div>
<p data-enonce class="mt-3 text-lg font-extrabold">Complétez : la route par défaut s’écrit ___ via 192.168.1.1.</p>
<p class="mt-2 font-mono text-xs font-semibold">3 pts · utilisée 9 fois · réussite 29 %</p>
<div class="mt-4 flex flex-wrap gap-2"><button type="button" data-ajouter class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white hover:bg-[#ec3013]">+ Ajouter au sujet</button><a href="#editeur" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Modifier</a><button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Dupliquer</button></div>
</li>
</ul>
</section>
<aside class="grid content-start gap-8 lg:col-span-4">
<section class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-6 lg:sticky lg:top-6" aria-labelledby="t-sujet">
<h2 id="t-sujet" class="text-2xl font-extrabold">Sujet en cours</h2>
<label class="mt-4 grid gap-2 font-extrabold">Titre<input value="Examen · Adressage IPv4" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"></label>
<ol id="sujet" class="mt-4 grid gap-2 font-semibold"><li data-vide class="border-2 border-dashed border-black bg-white p-3">Ajoutez des questions depuis la liste.</li></ol>
<p class="mt-4 font-mono font-semibold"><span id="nb-q">0</span> question(s) · <span id="nb-pts">0</span> point(s)</p>
<fieldset class="mt-4 grid gap-2 font-semibold"><legend class="font-extrabold">Options</legend>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Mélanger les questions</label>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Ajouter une partie TP</label>
<label class="flex items-center gap-3"><input type="checkbox" class="h-5 w-5 accent-black"> Corrections visibles après l’épreuve</label>
</fieldset>
<a href="{{ route('examen') }}" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013] disabled:cursor-not-allowed disabled:bg-[#444141] disabled:shadow-none mt-6">Programmer l’examen</a>
</section>
</aside>
</div>
<section id="editeur" class="scroll-mt-6 border-t border-[#e3e5e8] bg-[#eef0fd]" aria-labelledby="t-editeur">
<div class="mx-auto max-w-7xl px-5 py-14 lg:px-10">
<h2 id="t-editeur" class="text-4xl font-extrabold tracking-tight">Créer ou modifier une question</h2>
<form class="mt-8 grid gap-5 border border-[#e3e5e8] rounded-2xl bg-white p-7 lg:grid-cols-2" onsubmit="event.preventDefault(); this.querySelector('[data-ok]').hidden = false;">
<label class="grid gap-2 font-extrabold lg:col-span-2">Énoncé<textarea rows="2" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none">Quel masque correspond à /26 ?</textarea></label>
<label class="grid gap-2 font-extrabold">Type<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>Choix unique</option><option>Choix multiple</option><option>Vrai / faux</option><option>Réponse numérique</option><option>Réponse courte</option><option>Texte à trous</option></select></label>
<div class="grid grid-cols-2 gap-4"><label class="grid gap-2 font-extrabold">Points<input type="number" value="1" min="0" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"></label><label class="grid gap-2 font-extrabold">Difficulté<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>Facile</option><option selected>Moyen</option><option>Difficile</option></select></label></div>
<fieldset class="grid gap-3 lg:col-span-2"><legend class="font-extrabold">Réponses <span class="font-semibold">(cochez la bonne)</span></legend>
<label class="flex items-center gap-3"><input type="radio" name="bonne" class="h-5 w-5 shrink-0 accent-black"><input value="255.255.255.128" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none font-mono" aria-label="Réponse 1"></label>
<label class="flex items-center gap-3"><input type="radio" name="bonne" checked class="h-5 w-5 shrink-0 accent-black"><input value="255.255.255.192" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none font-mono" aria-label="Réponse 2"></label>
<label class="flex items-center gap-3"><input type="radio" name="bonne" class="h-5 w-5 shrink-0 accent-black"><input value="255.255.255.224" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none font-mono" aria-label="Réponse 3"></label>
<label class="flex items-center gap-3"><input type="radio" name="bonne" class="h-5 w-5 shrink-0 accent-black"><input value="255.255.255.240" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none font-mono" aria-label="Réponse 4"></label>
</fieldset>
<label class="grid gap-2 font-extrabold lg:col-span-2">Explication montrée à l’élève<textarea rows="2" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none">26 bits = 24 bits (255.255.255) + 2 bits dans le dernier octet : 128 + 64 = 192.</textarea></label>
<label class="grid gap-2 font-extrabold">Cursus<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>BTS SIO · Bloc 2</option><option>BTS CIEL · Réseaux</option><option>NSI · Terminale</option><option>BUT R&amp;T · S1</option><option>TSSR · CCP 2</option></select></label>
<label class="grid gap-2 font-extrabold">Notion<input value="Adressage IPv4" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"></label>
<div class="flex flex-wrap items-center gap-4 lg:col-span-2"><button type="submit" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013] disabled:cursor-not-allowed disabled:bg-[#444141] disabled:shadow-none">Enregistrer dans ma banque</button><label class="flex items-center gap-3 font-semibold"><input type="checkbox" class="h-5 w-5 accent-black"> Partager avec mon établissement</label><p data-ok hidden class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-4 py-2 font-extrabold">Question enregistrée ✓</p></div>
</form>
</div>
</section>
<script>
(function () {
var sujet = document.getElementById('sujet'), nbq = document.getElementById('nb-q'), nbp = document.getElementById('nb-pts'), q = 0, p = 0;
document.querySelectorAll('[data-ajouter]').forEach(function (b) {
b.addEventListener('click', function () {
var li = b.closest('[data-question]');
if (b.disabled) return;
var vide = sujet.querySelector('[data-vide]'); if (vide) vide.remove();
q++; p += Number(li.dataset.pts);
var it = document.createElement('li');
it.className = 'flex gap-3 border border-[#dadce0] rounded-lg bg-white p-3';
it.innerHTML = '<span class="font-mono font-semibold">' + q + '</span><span>' + li.querySelector('[data-enonce]').textContent + '</span>';
sujet.appendChild(it);
nbq.textContent = q; nbp.textContent = p;
b.disabled = true; b.textContent = 'Ajoutée ✓'; b.classList.remove('bg-black', 'text-white'); b.classList.add('bg-[#e6f4ea]');
});
});
document.querySelectorAll('[data-outil]').forEach(function (b) { b.addEventListener('click', function () { b.setAttribute('aria-pressed', b.getAttribute('aria-pressed') !== 'true'); }); });
document.getElementById('flash-go').addEventListener('click', function () {
var sel = Array.prototype.filter.call(document.querySelectorAll('[data-outil]'), function (b) { return b.getAttribute('aria-pressed') === 'true'; }).map(function (b) { return b.textContent; });
var r = document.getElementById('flash-res'); r.hidden = false;
if (!sel.length) { r.textContent = 'Choisissez au moins un outil.'; return; }
r.textContent = 'Ouverture du diaporama…'; location.href = '{{ route('quiz.projection') }}';
});
var rech = document.getElementById('recherche');
rech.addEventListener('input', function () {
var v = rech.value.toLowerCase();
document.querySelectorAll('[data-question]').forEach(function (li) { li.hidden = v && li.textContent.toLowerCase().indexOf(v) === -1; });
});
})();
</script>
@endsection

View file

@ -0,0 +1,121 @@
@extends('layouts.vitrine')
@section('titre', 'Bibliothèque')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto max-w-7xl px-5 pb-12 pt-12 lg:px-10">
<p class="inline-block border border-[#dadce0] rounded-lg bg-[#eef0fd] px-3 py-1 text-sm font-bold">Bibliothèque du prof</p>
<div class="min-w-0 flex-1"><p data-public="P" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#1d3fa8]">Pour les profs</p>
<h1 class="mt-6 max-w-5xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Tout le référentiel, fiche par fiche.</h1></div>
<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 border-[#e3e5e8] rounded-2xl sm:grid-cols-5"></dl>
<div class="mt-6 max-w-4xl border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-4 text-sm font-bold"><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 border-[#e3e5e8] 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 border-[#e3e5e8] rounded-2xl 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 border-[#e3e5e8] 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 border-[#e3e5e8] 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 border-[#e3e5e8] rounded-2xl px-3 py-2 font-semibold focus:bg-[#f8f9fa] focus:outline-none" placeholder="Rechercher : OSPF, chmod, RSA…" aria-label="Rechercher">
<select id="b-theme" class="border border-[#e3e5e8] rounded-2xl 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 border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] 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 border-[#dadce0] rounded-lg 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 border-[#dadce0] rounded-lg bg-[#fef7e0] 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 border-[#dadce0] rounded-lg bg-[#eef0fd] 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 border-[#dadce0] rounded-lg bg-[#e6f4ea] 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 border-[#dadce0] rounded-lg bg-[#e6f4ea] 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 border-[#dadce0] rounded-lg 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 border-[#dadce0] rounded-lg bg-[#fce8e6] 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 border-[#dadce0] rounded-lg 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 border-[#dadce0] rounded-lg 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 border-[#dadce0] rounded-lg bg-[#0b57d0] 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-fiche="{{ route('cours.fiche') }}" 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 src="{{ asset('js/contenus-1.js') }}"></script>
<script src="{{ asset('js/contenus-2.js') }}"></script>
<script src="{{ asset('js/contenus-3.js') }}"></script>
<script src="{{ asset('js/contenus-exemples.js') }}"></script>
<script src="{{ asset('js/contenus-reseau-1.js') }}"></script>
<script src="{{ asset('js/contenus-reseau-2.js') }}"></script>
<script src="{{ asset('js/contenus-devops-1.js') }}"></script>
<script src="{{ asset('js/contenus-devops-2.js') }}"></script>
<script src="{{ asset('js/contenus-infra-3.js') }}"></script>
<script src="{{ asset('js/contenus-data-4.js') }}"></script>
<script src="{{ asset('js/contenus-sys-5.js') }}"></script>
<script src="{{ asset('js/contenus-lot-6.js') }}"></script>
<script src="{{ asset('js/contenus-lot-7.js') }}"></script>
<script src="{{ asset('js/contenus-lot-8.js') }}"></script>
<script src="{{ asset('js/contenus-lot-9.js') }}"></script>
<script src="{{ asset('js/contenus-lot-10.js') }}"></script>
<script src="{{ asset('js/contenus-lot-11.js') }}"></script>
<script src="{{ asset('js/contenus-lot-12.js') }}"></script>
<script src="{{ asset('js/contenus-alias.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-[#fef7e0]","TD":"bg-[#eef0fd]","LAB":"bg-[#e6f4ea]","LAB+":"bg-[#e6f4ea]","IDE":"bg-[#13233A] text-white","GEN":"bg-[#fce8e6]","EXAM":"bg-[#ec3013] text-white","PROJ":"bg-white","CTF":"bg-[#0b57d0] text-white"}; BG.HV = 'bg-white border-dashed';
var U = box.dataset;
var KW = { ipv6: /ipv6/i, projet: /projet|sa[ée]|scrum|agile|itil|pilpro|erp|management|gestion|lean|comptabilit|cejm|épreuve|examen|grand oral|sre|observabilit/i, maths: /math|signal|transmission|modulation|suite|matrice|probab|fourier|complexe|ensemble|trigonom|intégral|différenti|numérisation|décibel/i, fichiers: /fichier|nfs|ftp|ntp|temps|glpi|inventaire|bonding|agrégation|tssr|ais|maintenir|infrastructure/i, archi: /architecture|processeur|mémoire|matériel|composant|machine|système d’exploitation|os\b/i, iot: /iot|node-red|modbus|coap|chaîne d’information|chaîne d’énergie|objet|capteur|embarqué|électronique|microcontr|arduino|esp32|mqtt|domotique/i, voip: /voip|téléphon|sip|voix|toip|visioconf/i, pandas: /pandas|donnée|data|statistique|tableau|csv|visualis/i, ml: /éthique|biais|ai act|kafka|spark|flux temps réel|distribué|apprentissage|machine learning|\bia\b|intelligence artificielle|modèle|knn|voisins|prédict/i, neurones: /neurone|deep|ocr|vocal|image|vision|langage/i, k8s: /kubernetes|orchestr|cloud|cluster/i, supervision: /supervision|monitoring|zabbix|prometheus|snmp|journalisation|logs centralis/i, annuaire: /ldap|active directory|annuaire|gpo|samba|identit|authentification|kerberos/i, git: /\bgit\b|version|collabor/i, cicd: /ci\/cd|pipeline|intégration continue|déploiement/i, docker: /docker|conteneur|virtualisation|devops|devcloud|cloud/i, compose: /compose/i, ansible: /ansible|iac|automatis|ci\/cd|pipeline/i, binaire: /binaire|hexa|représentation|entiers|codage/i, terminal: /terminal|linux|shell|commande|debian|système|fichiers|cp, mv|cat, less|nano|vim|processus|systemd|journalctl|apt|paquets|tar|archiv|compression|cron|planification|performance|noyau|démarrage|grub|sauvegarde|rsync|lvm/i, droits: /droits|permission|utilisateur|groupe|chmod|compte/i, tubes: /bash|script|grep|journaux|log|automatis|expressions régulières|regex/i, osi: /osi|tcp\/ip|couche|encapsulation|réseau|protocole|internet/i, sql: /sql|données|base|requête|mcd|merise|relationnel|group by|agrégats|ddl|dml|create|insert|vues|procédures|triggers|transactions|acid|index|explain|normalisation|réplication/i, python: /python|programm|algorithm|développ|code|fonction|listes|tuples|dictionnaires|chaînes|récursiv|tests|pytest|tris|dichotom|complexité|piles|graphes|pandas|json|csv|types construits/i, web: /web|photographie|pixel|rvb|exif|gps|nmea|cartographie|histoire|anglais|html|css|http|site|cms|apache|php|javascript|nginx|reverse proxy|proxy|api rest|laravel|mvc|oauth|authentification|framework/i, crypto: /crypto|sécurité|cyber|chiffr|mot de passe|ssh|tls|certificat|rgpd|gpg|vpn|wireguard|ipsec|fail2ban|force brute|nmap|scan|vulnérab|cve|ids|suricata|anssi|menaces|hameçonnage|rançongiciel|iso 27001|ebios|pssi|nis2|ctf|dmz|hygiène/i, diagnostic: /diagnostic|dépannage|incident|ping|supervision|maintenance|arp|tcp et udp|ss\b|tcpdump|pcap|trames|analyse de trames/i, ipv4: /ipv4|adressage|masque|cidr|sous-réseau|vlsm|plan d/i, vlan: /vlan|802\.1q|commutation|switch|ethernet|trunk/i, dhcp: /dhcp|bail|adresse automatique/i, dns: /dns|domaine|nom de|messagerie|postfix|dkim|dmarc/i, nat: /nat|pat|passerelle|pare-feu|nftables|firewall|dmz/i, routage: /routage|routeur|route|ospf|rip|interconnex|bgp|mpls|vrrp|keepalived/i };
var PRO = (window.CONTENUS_PRO || []).filter(function (c) { return c.intro; });
var statut = function (t) { if (PRO.some(function (c) { return c.match.test(t); })) return ['Complet', 'bg-[#e6f4ea]']; var p = [t].concat(t.split(/\s*[:,;·]\s*|\s+et\s+/)); if (PRO.some(function (c) { return p.some(function (x) { return x.length > 1 && (c.match.test(x) || (KW[c.id] && KW[c.id].test(x))); }); })) return ['Lié', 'bg-[#fef7e0]']; return ['Bientôt', 'bg-white']; };
var badgeS = function (t) { var s = statut(t); return '<span class="border border-[#dadce0] rounded-lg ' + s[1] + ' px-1.5 text-[11px] font-extrabold">' + s[0] + '</span>'; };
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 border-[#dadce0] rounded-lg ' + (BG[t] || 'bg-white') + ' px-1.5 font-mono text-[11px] font-semibold">' + (t === 'HV' ? 'hors VM' : t) + '</span>'; }).join(''); };
var lienT = function (f) { var t = f.tags.split(' '); if (t.indexOf('IDE') > -1 || t.indexOf('GEN') > -1 || t.indexOf('LAB') > -1 || t.indexOf('EXAM') > -1) return lien(f.tags); return U.urlFiche + '?chapitre=' + encodeURIComponent(f.t); };
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-[#fef7e0]'], ['Labs', nb('LAB') + nb('LAB+'), 'bg-[#e6f4ea]'], ['Formations', R.formations.length, 'bg-[#eef0fd]'], ['Examens', R.examens.length + nb('EXAM'), 'bg-[#fce8e6]']].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-extrabold">' + 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 border-[#e3e5e8] rounded-2xl bg-white p-4"><div class="flex items-start justify-between gap-2"><span class="border border-[#dadce0] rounded-lg 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(t) + badges(tags) + '</div><div class="flex flex-wrap gap-2 border-t border-[#e3e5e8] pt-3"><a href="' + lien(tags) + '" class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 py-0.5 text-sm font-extrabold hover:bg-[#0b57d0] hover:text-white">Ouvrir</a><button type="button" data-ajout class="border border-[#dadce0] rounded-lg bg-white px-2 py-0.5 text-sm font-extrabold hover:bg-[#e6f4ea]">+ 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-extrabold tracking-tight"><span class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] px-2 font-mono text-2xl">' + 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 border-[#e3e5e8] rounded-2xl bg-white" open><summary class="cursor-pointer border-b border-[#e3e5e8] bg-[#e6f4ea] px-5 py-3 text-xl font-extrabold">' + esc(f.nom) + ' <span class="font-mono text-sm font-semibold">· ' + ch.length + ' chapitre(s)</span></summary><ul class="divide-y divide-[#e3e5e8]">' + 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="' + (/IDE|GEN|LAB|EXAM/.test(c[1]) ? lien(c[1]) : U.urlFiche + '?chapitre=' + encodeURIComponent(c[0])) + '" class="min-w-0 flex-1 font-bold hover:underline">' + esc(c[0]) + '</a><span class="flex flex-wrap gap-1">' + badgeS(c[0]) + badges(c[1]) + '</span><button type="button" data-ajout class="border border-[#dadce0] rounded-lg px-2 text-xs font-extrabold hover:bg-[#e6f4ea]">+ Séquence</button></li>'; }).join('') + '</ul></details>';
}).join('');
if (bloc) h += '<section class="mb-12"><h2 class="text-3xl font-extrabold 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-extrabold 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 border-[#e3e5e8] rounded-2xl bg-white p-5"><p class="font-mono text-sm font-semibold">⏱ ' + e[2] + '</p><p class="mt-2 text-xl font-extrabold">' + 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 border-[#dadce0] rounded-lg bg-[#ec3013] px-2 py-0.5 text-sm font-extrabold text-white">Aperçu</a><a href="' + U.urlBanque + '" class="border border-[#dadce0] rounded-lg bg-white px-2 py-0.5 text-sm font-extrabold hover:bg-[#fef7e0]">Personnaliser</a></div></li>'; }).join('') + '</ul></section>';
h += '<section><h2 class="text-3xl font-extrabold 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 border-[#e3e5e8] rounded-2xl bg-white p-6 text-xl font-extrabold">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-[#e6f4ea]'); });
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

View file

@ -0,0 +1,157 @@
@extends('layouts.vitrine')
@section('titre', 'Suivi de classe')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-end gap-6 px-5 pb-10 pt-10 lg:px-10">
<div class="flex-1">
<p class="font-mono text-sm font-semibold">Espace enseignant · Suivi</p>
<div class="min-w-0 flex-1"><p data-public="P" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#1d3fa8]">Pour les profs</p>
<h1 class="mt-2 text-5xl font-extrabold leading-[0.95] tracking-tight sm:text-6xl">BTS SIO 1 · Groupe A</h1></div>
<p class="mt-3 text-lg font-semibold">Bloc 2 · Administration des systèmes et des réseaux · 24 élèves</p>
</div>
<div class="flex flex-wrap gap-3">
<a href="{{ route('banque') }}#flash" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-5 py-3 font-extrabold">Quiz flash de début d’heure</a>
<a href="{{ route('devoirs') }}" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold hover:bg-[#fef7e0]">Devoirs maison</a>
<a href="{{ route('cours.show') }}" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold transition-transform hover:bg-[#fef7e0] active:shadow-none">Voir la séquence</a>
<button type="button" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold transition-transform hover:bg-[#fef7e0] active:shadow-none">Exporter les notes (CSV)</button>
</div>
</div>
</section>
<div class="mx-auto max-w-7xl px-5 py-10 lg:px-10">
<dl class="grid grid-cols-2 gap-5 lg:grid-cols-4">
<div class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-5"><dt class="font-semibold">Progression moyenne</dt><dd class="mt-1 font-mono text-4xl font-semibold">52 %</dd></div>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-5"><dt class="font-semibold">Moyenne aux QCM</dt><dd class="mt-1 font-mono text-4xl font-semibold">13,4</dd></div>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-5"><dt class="font-semibold">Actifs cette semaine</dt><dd class="mt-1 font-mono text-4xl font-semibold">21 / 24</dd></div>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#ec3013] p-5 text-white"><dt class="font-semibold">À aider maintenant</dt><dd class="mt-1 font-mono text-4xl font-semibold">2</dd></div>
</dl>
<div class="mt-14 grid gap-10 lg:grid-cols-12">
<section class="lg:col-span-8" aria-labelledby="t-tab">
<h2 id="t-tab" class="text-3xl font-extrabold">Élèves</h2>
<div class="mt-5 overflow-x-auto border border-[#e3e5e8] rounded-2xl bg-white">
<table class="w-full min-w-[760px] text-left">
<thead class="bg-[#0b57d0] text-white"><tr><th class="px-4 py-3">Élève</th><th class="px-3 py-3 font-mono text-xs font-semibold">Adressage IPv4</th><th class="px-3 py-3 font-mono text-xs font-semibold">VLAN</th><th class="px-3 py-3 font-mono text-xs font-semibold">Inter-VLAN</th><th class="px-3 py-3 font-mono text-xs font-semibold">DHCP</th><th class="px-3 py-3 font-mono text-xs font-semibold">DNS BIND</th><th class="px-3 py-3">QCM</th><th class="px-3 py-3">Temps VM</th></tr></thead>
<tbody class="divide-y divide-[#e3e5e8]">
<tr class="">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-[#e6f4ea] font-extrabold">L</span><span><span class="block font-extrabold">Léa M.</span><span class="block font-mono text-xs font-semibold">Terminé</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="3 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">18/20</td>
<td class="px-3 py-3 font-mono text-sm">12 h 40</td>
</tr>
<tr class="">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-white font-extrabold">Y</span><span><span class="block font-extrabold">Yanis B.</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="3 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="1 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">14/20</td>
<td class="px-3 py-3 font-mono text-sm">9 h 10</td>
</tr>
<tr class="bg-[#FFD9E8]">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-[#fce8e6] font-extrabold">N</span><span><span class="block font-extrabold">Nora Kaci</span><span class="block font-mono text-xs font-semibold">Main levée</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="2 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">11/20</td>
<td class="px-3 py-3 font-mono text-sm">8 h 05</td>
</tr>
<tr class="">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-white font-extrabold">T</span><span><span class="block font-extrabold">Tom R.</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="2 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">16/20</td>
<td class="px-3 py-3 font-mono text-sm">10 h 30</td>
</tr>
<tr class="">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-white font-extrabold">I</span><span><span class="block font-extrabold">Inès D.</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="2 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">9/20</td>
<td class="px-3 py-3 font-mono text-sm">5 h 20</td>
</tr>
<tr class="bg-[#FFE4DF]">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-[#ec3013] font-extrabold text-white">S</span><span><span class="block font-extrabold">Sami L.</span><span class="block font-mono text-xs font-semibold">Bloqué 9 min</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="3 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="1 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">7/20</td>
<td class="px-3 py-3 font-mono text-sm">6 h 45</td>
</tr>
<tr class="">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-[#e6f4ea] font-extrabold">C</span><span><span class="block font-extrabold">Chloé P.</span><span class="block font-mono text-xs font-semibold">En avance</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="1 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">19/20</td>
<td class="px-3 py-3 font-mono text-sm">13 h 15</td>
</tr>
<tr class="">
<td class="px-4 py-3"><span class="flex items-center gap-3"><span class="grid h-8 w-8 place-items-center border border-[#dadce0] rounded-lg bg-white font-extrabold">A</span><span><span class="block font-extrabold">Adam F.</span></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="4 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="3 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-black"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3"><span class="grid grid-cols-4 gap-0.5" title="0 / 4 étapes"><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-4 w-3 border border-[#dadce0] rounded-lg bg-white"></span></span></td>
<td class="px-3 py-3 font-mono font-semibold">13/20</td>
<td class="px-3 py-3 font-mono text-sm">8 h 50</td>
</tr>
</tbody>
</table>
</div>
<p class="mt-4 font-semibold">8 élèves sur 24 affichés · triés par besoin d’aide</p>
</section>
<aside class="grid content-start gap-8 lg:col-span-4">
<section class="border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] p-6" aria-labelledby="t-nora">
<p class="font-mono text-sm font-semibold">Fiche élève</p>
<h2 id="t-nora" class="mt-1 text-3xl font-extrabold">Nora Kaci</h2>
<ol class="mt-5 grid gap-3 border-l border-[#e3e5e8] pl-4 font-semibold">
<li><span class="font-mono text-xs">10:42</span><br>Main levée · Inter-VLAN, étape 3</li>
<li><span class="font-mono text-xs">10:31</span><br>Étape 2 validée après 3 essais</li>
<li><span class="font-mono text-xs">Mar.</span><br>QCM Adressage IPv4 : 11/20. Erreurs sur le calcul de l’adresse réseau (/22).</li>
</ol>
<div class="mt-6 flex flex-wrap gap-3">
<a href="{{ route('labs.essai') }}" class="border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2 font-extrabold hover:bg-[#fef7e0]">Ouvrir sa console</a>
<a href="{{ route('cours.show') }}" class="border border-[#e3e5e8] rounded-2xl bg-black px-4 py-2 font-extrabold text-white hover:bg-[#13233A]">Lui assigner le TD</a>
</div>
</section>
<section class="border border-[#e3e5e8] rounded-2xl bg-white p-6" aria-labelledby="t-exam">
<h2 id="t-exam" class="text-3xl font-extrabold">Mode examen</h2>
<a href="{{ route('banque') }}" class="mt-3 inline-block font-extrabold underline underline-offset-4">Composer un sujet dans la banque →</a>
<form action="{{ route('examen') }}" method="get" class="mt-5 grid gap-4">
<label class="grid gap-2 font-extrabold">Épreuve<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>Adressage et VLAN · E6 blanc SISR</option><option>QCM Bloc 2</option></select></label>
<label class="grid gap-2 font-extrabold">Durée<select class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none"><option>1 h</option><option>2 h</option><option>4 h</option></select></label>
<fieldset class="grid gap-2 font-semibold">
<legend class="font-extrabold">Pendant l’épreuve</legend>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Indices désactivés</label>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Copier-coller bloqué</label>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Sortie d’onglet signalée</label>
<label class="flex items-center gap-3"><input type="checkbox" class="h-5 w-5 accent-black"> Ordre des questions mélangé</label>
</fieldset>
<button type="submit" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013].5.5 active:shadow-none">Lancer l’examen</button>
</form>
</section>
</aside>
</div>
</div>
@endsection

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,243 @@
@extends('layouts.vitrine')
@section('titre', 'CM · Adressage IPv4')
@section('contenu')
<div class="sticky top-0 z-30 border-b border-[#e3e5e8] bg-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-center gap-4 px-5 py-3 lg:px-10">
<span class="border border-[#dadce0] rounded-lg bg-white px-2 font-mono text-sm font-semibold">CM</span>
<p class="min-w-0 flex-1 truncate font-extrabold">Adressage IPv4 et sous-réseaux</p>
<p class="font-mono text-sm font-semibold">Lu : <span id="pct">0</span> %</p>
<p class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-3 py-1 font-mono font-semibold" role="timer"><span aria-hidden="true">⏱</span><span id="chrono">00:00</span><span class="text-xs">/ 20:00 conseillées</span></p>
</div>
<div class="h-2 bg-white"><div id="barre-lecture" class="h-full w-0 bg-[#ec3013]"></div></div>
</div>
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto max-w-7xl px-5 pb-12 pt-10 lg:px-10">
<nav aria-label="Fil d’Ariane" class="flex flex-wrap gap-2 font-semibold"><a href="{{ route('cours.index') }}" class="underline underline-offset-4">Cours</a><span>/</span><a href="{{ route('cours.show') }}" class="underline underline-offset-4">Adressage IPv4</a><span>/</span><span>CM</span></nav>
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="mt-6 max-w-4xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Adressage IPv4 et sous-réseaux</h1></div>
<p class="mt-6 max-w-2xl text-xl font-medium leading-relaxed">Lis le cours jusqu’au bout. Le QCM de lecture se débloque quand toutes les parties ont été lues et que 5 minutes se sont écoulées.</p>
<ol class="mt-8 flex flex-wrap gap-2 text-sm font-extrabold" aria-label="Parcours">
<li class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 text-white">1 · CM</li><li class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-3 py-1">2 · QCM de lecture</li><li class="border-2 border-dashed border-black bg-white px-3 py-1">3 · TD optionnel</li><li class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-3 py-1">4 · TP</li><li class="border border-[#dadce0] rounded-lg bg-[#ec3013] px-3 py-1 text-white">5 · Examen</li>
</ol>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-12 px-5 py-14 lg:grid-cols-12 lg:px-10">
<nav class="lg:col-span-3" aria-label="Parties du cours">
<ol class="sticky top-24 grid gap-2">
<li><a href="#pourquoi" data-lien="pourquoi" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>1. Pourquoi des adresses ?</a></li>
<li><a href="#bits" data-lien="bits" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>2. Une adresse, 32 bits</a></li>
<li><a href="#masque" data-lien="masque" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>3. Le masque de sous-réseau</a></li>
<li><a href="#et" data-lien="et" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>4. Trouver l’adresse réseau : le ET logique</a></li>
<li><a href="#diffusion" data-lien="diffusion" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>5. Diffusion et nombre d’hôtes</a></li>
<li><a href="#decoupe" data-lien="decoupe" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>6. Découper un réseau en sous-réseaux</a></li>
<li><a href="#privees" data-lien="privees" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>7. Adresses privées et adresses particulières</a></li>
<li><a href="#retenir" data-lien="retenir" class="flex items-center gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#f8f9fa]"><span data-coche class="grid h-5 w-5 shrink-0 place-items-center border border-[#dadce0] rounded-lg text-xs"></span>8. À retenir</a></li>
</ol>
</nav>
<article class="grid gap-16 text-lg font-medium leading-relaxed lg:col-span-9">
<section id="pourquoi" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-pourquoi">
<h2 id="t-pourquoi" class="text-4xl font-extrabold leading-tight tracking-tight">1. Pourquoi des adresses ?</h2>
<p>Sur un réseau, chaque machine doit pouvoir être trouvée. Comme une lettre a besoin d’une adresse postale, un paquet a besoin d’une adresse IP de destination.</p>
<div class="grid gap-4 sm:grid-cols-2">
<div class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-5"><p class="font-mono text-sm font-semibold">La rue</p><p class="mt-1 text-2xl font-extrabold">= le réseau</p><p class="mt-2 font-semibold">Toutes les maisons de la rue partagent le même nom de rue.</p></div>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-5"><p class="font-mono text-sm font-semibold">Le numéro</p><p class="mt-1 text-2xl font-extrabold">= l’hôte</p><p class="mt-2 font-semibold">Chaque maison a son numéro, unique dans la rue.</p></div>
</div>
<p>Une adresse IPv4 contient les deux informations. Le <strong>masque</strong> indique où s’arrête la rue et où commence le numéro.</p>
</section>
<section id="video" class="grid scroll-mt-28 gap-4 border border-[#e3e5e8] rounded-2xl bg-[#13233A] p-6 text-white" aria-labelledby="t-video">
<h2 id="t-video" class="text-3xl font-extrabold">Vidéo de contexte</h2>
<div id="v-cadre" class="grid aspect-video place-items-center border border-[#e3e5e8] rounded-2xl bg-[#0D192B] text-center"><p class="max-w-md px-4 font-semibold text-[#9fb0c8]">Ton prof peut ajouter ici une vidéo YouTube pour illustrer le cours.</p></div>
<form id="v-form" class="flex flex-wrap gap-3"><label class="sr-only" for="v-url">Lien YouTube</label><input id="v-url" class="min-w-[240px] flex-1 border border-[#e3e5e8] rounded-2xl px-3 py-2 font-mono text-sm font-semibold text-black" placeholder="https://www.youtube.com/watch?v=…"><button type="submit" class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-4 py-2 font-extrabold text-black">Intégrer la vidéo</button></form>
<p class="text-sm font-semibold text-[#9fb0c8]">Espace prof · la vidéo s’affiche en mode sans cookie (youtube-nocookie.com).</p>
</section>
<section id="bits" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-bits">
<h2 id="t-bits" class="text-4xl font-extrabold leading-tight tracking-tight">2. Une adresse, 32 bits</h2>
<p>Une adresse IPv4 est un nombre de <strong>32 bits</strong>. Pour la lire plus facilement, on la découpe en 4 octets de 8 bits, écrits en décimal et séparés par des points.</p>
<figure class="overflow-x-auto border border-[#e3e5e8] rounded-2xl bg-white p-5">
<p class="font-mono text-2xl font-semibold">192.168.10.77</p>
<div class="mt-4 flex min-w-max items-end gap-1"><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span></span><span class="self-end px-0.5 font-extrabold">.</span><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span></span><span class="self-end px-0.5 font-extrabold">.</span><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span></span><span class="self-end px-0.5 font-extrabold">.</span><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-white">1</span></span></div>
<figcaption class="mt-3 font-semibold">192 = 11000000 · 168 = 10101000 · 10 = 00001010 · 77 = 01001101</figcaption>
</figure>
<p>Chaque octet va de 0 (00000000) à 255 (11111111). Une adresse comme 192.168.10.300 est donc impossible.</p>
</section>
<section id="masque" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-masque">
<h2 id="t-masque" class="text-4xl font-extrabold leading-tight tracking-tight">3. Le masque de sous-réseau</h2>
<p>Le masque est lui aussi un nombre de 32 bits. Il commence par une suite de 1 (la partie réseau) suivie d’une suite de 0 (la partie hôte). La notation <strong>CIDR</strong> écrit simplement le nombre de 1 : <code class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-1 font-mono">/26</code>.</p>
<figure class="overflow-x-auto border border-[#e3e5e8] rounded-2xl bg-white p-5">
<p class="font-mono text-2xl font-semibold">/26 = 255.255.255.192</p>
<div class="mt-4 flex min-w-max items-end gap-1"><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span></span><span class="self-end px-0.5 font-extrabold">.</span><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span></span><span class="self-end px-0.5 font-extrabold">.</span><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span></span><span class="self-end px-0.5 font-extrabold">.</span><span class="flex gap-0.5"><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#eef0fd]">1</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#e6f4ea]">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#e6f4ea]">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#e6f4ea]">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#e6f4ea]">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#e6f4ea]">0</span><span class="grid h-7 w-5 place-items-center border border-[#dadce0] rounded-lg font-mono text-xs font-semibold bg-[#e6f4ea]">0</span></span></div>
<figcaption class="mt-3 flex flex-wrap gap-4 font-semibold"><span class="flex items-center gap-2"><span class="h-4 w-4 border border-[#dadce0] rounded-lg bg-[#eef0fd]"></span>26 bits de réseau</span><span class="flex items-center gap-2"><span class="h-4 w-4 border border-[#dadce0] rounded-lg bg-[#e6f4ea]"></span>6 bits d’hôte</span></figcaption>
</figure>
<p>Dans le dernier octet, les 2 premiers bits valent 1 : 128 + 64 = 192. D’où 255.255.255.192.</p>
</section>
<section id="et" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-et">
<h2 id="t-et" class="text-4xl font-extrabold leading-tight tracking-tight">4. Trouver l’adresse réseau : le ET logique</h2>
<p>Pour trouver le réseau d’une adresse, on fait un <strong>ET logique</strong> bit à bit entre l’adresse et le masque. Le résultat vaut 1 seulement si les deux bits valent 1.</p>
<div class="grid gap-6 md:grid-cols-2">
<table class="border border-[#e3e5e8] rounded-2xl bg-white text-center font-mono text-lg"><caption class="sr-only">Table du ET logique</caption><thead class="bg-[#0b57d0] text-white"><tr><th class="px-4 py-2">A</th><th class="px-4 py-2">B</th><th class="px-4 py-2">A ET B</th></tr></thead><tbody class="divide-y divide-[#e3e5e8]"><tr><td class="py-1">0</td><td>0</td><td class="font-semibold">0</td></tr><tr><td class="py-1">0</td><td>1</td><td class="font-semibold">0</td></tr><tr><td class="py-1">1</td><td>0</td><td class="font-semibold">0</td></tr><tr class="bg-[#fef7e0]"><td class="py-1">1</td><td>1</td><td class="font-semibold">1</td></tr></tbody></table>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#13233A] p-5 font-mono text-white">
<p class="text-sm text-[#9fb0c8]">Dernier octet seulement</p>
<p class="mt-2"> 01001101 <span class="text-[#9fb0c8]">(77)</span></p>
<p>ET 11000000 <span class="text-[#9fb0c8]">(192)</span></p>
<p class="border-t-2 border-white pt-1 text-[#FFD23F]">= 01000000 (64)</p>
</div>
</div>
<p>Les trois premiers octets du masque valent 255 : ils recopient l’adresse telle quelle. L’adresse réseau de 192.168.10.77/26 est donc <strong>192.168.10.64</strong>.</p>
</section>
<section id="diffusion" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-diffusion">
<h2 id="t-diffusion" class="text-4xl font-extrabold leading-tight tracking-tight">5. Diffusion et nombre d’hôtes</h2>
<p>L’adresse de <strong>diffusion</strong> (broadcast) met tous les bits d’hôte à 1. Un paquet envoyé à cette adresse arrive à toutes les machines du réseau.</p>
<p>Ici, les 6 bits d’hôte à 1 donnent 01111111 = 127 : la diffusion est <strong>192.168.10.127</strong>.</p>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] p-5 text-xl font-extrabold">Hôtes utilisables = 2<sup>bits d’hôte</sup> − 2</div>
<p>On retire 2 adresses : celle du réseau et celle de diffusion. Avec 6 bits : 2⁶ − 2 = <strong>62 hôtes</strong>, de 192.168.10.65 à 192.168.10.126.</p>
</section>
<section id="decoupe" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-decoupe">
<h2 id="t-decoupe" class="text-4xl font-extrabold leading-tight tracking-tight">6. Découper un réseau en sous-réseaux</h2>
<p>Emprunter des bits d’hôte pour le réseau crée des sous-réseaux plus petits. Emprunter 2 bits à un /24 donne 2² = 4 sous-réseaux en /26.</p>
<figure class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<p class="font-mono font-semibold">192.168.10.0/24 découpé en 4 × /26</p>
<div class="mt-4 grid grid-cols-4 border border-[#e3e5e8] rounded-2xl font-mono text-sm font-semibold">
<div class="border-r border-[#e3e5e8] bg-[#fef7e0] p-3">.0<br>→ .63</div><div class="border-r border-[#e3e5e8] bg-[#e6f4ea] p-3">.64<br>→ .127</div><div class="border-r border-[#e3e5e8] bg-[#eef0fd] p-3">.128<br>→ .191</div><div class="bg-[#fce8e6] p-3">.192<br>→ .255</div>
</div>
<figcaption class="mt-3 font-semibold">Chaque bloc : 64 adresses, 62 hôtes. L’adresse .77 tombe dans le 2ᵉ bloc.</figcaption>
</figure>
<p>Astuce : la taille d’un bloc vaut 256 moins la valeur du dernier octet du masque. Pour 192 : 256 − 192 = 64.</p>
</section>
<section id="privees" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-privees">
<h2 id="t-privees" class="text-4xl font-extrabold leading-tight tracking-tight">7. Adresses privées et adresses particulières</h2>
<p>Certaines plages sont réservées aux réseaux internes (RFC 1918). Elles ne sont pas routées sur Internet.</p>
<ul class="grid gap-3 sm:grid-cols-3"><li class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-4 font-mono text-lg font-semibold">10.0.0.0/8</li><li class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-4 font-mono text-lg font-semibold">172.16.0.0/12</li><li class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-4 font-mono text-lg font-semibold">192.168.0.0/16</li></ul>
<ul class="grid gap-2"><li class="flex flex-wrap gap-3"><span class="font-mono font-semibold">127.0.0.1</span><span>la boucle locale : la machine elle-même</span></li><li class="flex flex-wrap gap-3"><span class="font-mono font-semibold">169.254.x.x</span><span>adresse automatique quand aucun DHCP ne répond</span></li><li class="flex flex-wrap gap-3"><span class="font-mono font-semibold">0.0.0.0</span><span>« n’importe quelle adresse » ou « pas encore d’adresse »</span></li><li class="flex flex-wrap gap-3"><span class="font-mono font-semibold">255.255.255.255</span><span>diffusion limitée au réseau local</span></li></ul>
</section>
<section id="retenir" data-partie class="grid scroll-mt-28 gap-6" aria-labelledby="t-retenir">
<h2 id="t-retenir" class="text-4xl font-extrabold leading-tight tracking-tight">8. À retenir</h2>
<ul class="grid gap-3"><li class="flex gap-3 border border-[#dadce0] rounded-lg bg-white p-3 font-bold"><span aria-hidden="true">■</span><span>Une adresse IPv4 = 32 bits = 4 octets de 0 à 255.</span></li><li class="flex gap-3 border border-[#dadce0] rounded-lg bg-white p-3 font-bold"><span aria-hidden="true">■</span><span>Le masque sépare la partie réseau de la partie hôte. /n = n bits à 1.</span></li><li class="flex gap-3 border border-[#dadce0] rounded-lg bg-white p-3 font-bold"><span aria-hidden="true">■</span><span>Adresse réseau = adresse ET masque. Diffusion = bits d’hôte à 1.</span></li><li class="flex gap-3 border border-[#dadce0] rounded-lg bg-white p-3 font-bold"><span aria-hidden="true">■</span><span>Hôtes utilisables = 2<sup>bits d’hôte</sup> − 2.</span></li><li class="flex gap-3 border border-[#dadce0] rounded-lg bg-white p-3 font-bold"><span aria-hidden="true">■</span><span>Taille d’un bloc = 256 − dernier octet du masque.</span></li></ul>
</section>
<section id="qcm-lecture" class="scroll-mt-28 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-6" aria-labelledby="t-lecture">
<h2 id="t-lecture" class="text-4xl font-extrabold tracking-tight">QCM de lecture</h2>
<p class="mt-3 font-semibold">4 questions sur les notions du texte, pour vérifier que tu as bien lu.</p>
<div id="verrou" class="mt-6 border border-[#e3e5e8] rounded-2xl bg-white p-5">
<p class="text-xl font-extrabold">🔒 Encore un peu de lecture</p>
<p id="verrou-texte" class="mt-2 font-semibold">Parties lues : 0 / 8 · Temps : 0 / 5 min</p>
<button type="button" id="debloquer" class="mt-4 text-sm font-bold underline underline-offset-4">Aperçu : débloquer sans attendre</button>
</div>
<form id="form-lecture" hidden class="mt-6 grid gap-6">
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="2">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 1</legend>
<p class="text-xl font-extrabold">Combien de bits contient une adresse IPv4 ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l0" value="0" class="h-5 w-5 accent-black"><span>8</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l0" value="1" class="h-5 w-5 accent-black"><span>16</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l0" value="2" class="h-5 w-5 accent-black"><span>32</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l0" value="3" class="h-5 w-5 accent-black"><span>64</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4"><p data-verdict class="font-extrabold"></p><p class="mt-1 font-medium">Une adresse IPv4 fait 32 bits, découpés en 4 octets de 8 bits (partie 2).</p></div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="1">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 2</legend>
<p class="text-xl font-extrabold">Dans l’analogie de l’adresse postale, à quoi correspond le numéro de la maison ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l1" value="0" class="h-5 w-5 accent-black"><span>Au réseau</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l1" value="1" class="h-5 w-5 accent-black"><span>À l’hôte</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l1" value="2" class="h-5 w-5 accent-black"><span>Au masque</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l1" value="3" class="h-5 w-5 accent-black"><span>À la diffusion</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4"><p data-verdict class="font-extrabold"></p><p class="mt-1 font-medium">La rue représente le réseau, le numéro représente l’hôte, unique dans ce réseau (partie 1).</p></div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="2">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 3</legend>
<p class="text-xl font-extrabold">Quelle opération permet de trouver l’adresse réseau ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l2" value="0" class="h-5 w-5 accent-black"><span>Un OU logique</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l2" value="1" class="h-5 w-5 accent-black"><span>Une addition</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l2" value="2" class="h-5 w-5 accent-black"><span>Un ET logique</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l2" value="3" class="h-5 w-5 accent-black"><span>Une soustraction</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4"><p data-verdict class="font-extrabold"></p><p class="mt-1 font-medium">On fait un ET logique bit à bit entre l’adresse et le masque (partie 4).</p></div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="1">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 4</legend>
<p class="text-xl font-extrabold">Laquelle de ces adresses est privée ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l3" value="0" class="h-5 w-5 accent-black"><span>8.8.8.8</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l3" value="1" class="h-5 w-5 accent-black"><span>172.20.4.1</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l3" value="2" class="h-5 w-5 accent-black"><span>172.32.0.1</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="l3" value="3" class="h-5 w-5 accent-black"><span>193.168.1.1</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4"><p data-verdict class="font-extrabold"></p><p class="mt-1 font-medium">172.16.0.0/12 va de 172.16.0.0 à 172.31.255.255. 172.20.4.1 en fait partie, pas 172.32.0.1 (partie 7).</p></div>
</fieldset>
<div class="flex flex-wrap items-center gap-5"><button type="submit" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013] disabled:cursor-not-allowed disabled:bg-[#444141] disabled:shadow-none">Valider ma lecture</button><p id="score-lecture" hidden class="border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2 text-2xl font-extrabold"></p></div>
</form>
</section>
<section class="border border-[#e3e5e8] rounded-2xl bg-white p-6" aria-labelledby="t-plus">
<h2 id="t-plus" class="text-2xl font-extrabold">Pour aller plus loin</h2>
<p class="mt-2 font-semibold">Des plateformes externes pour s’entraîner encore, à ton rythme. Elles ne font pas partie de Syllabus.</p>
<div class="mt-4"><ul class="grid gap-2"><li><a href="https://www.hackerrank.com/domains/python" target="_blank" rel="noopener" class="flex items-center justify-between gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#fef7e0]"><span>HackerRank · Python</span><span class="font-mono" aria-hidden="true">↗</span></a></li><li><a href="https://www.hackerrank.com/domains/sql" target="_blank" rel="noopener" class="flex items-center justify-between gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#fef7e0]"><span>HackerRank · SQL</span><span class="font-mono" aria-hidden="true">↗</span></a></li><li><a href="https://www.hackerrank.com/domains/shell" target="_blank" rel="noopener" class="flex items-center justify-between gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#fef7e0]"><span>HackerRank · Linux Shell</span><span class="font-mono" aria-hidden="true">↗</span></a></li><li><a href="https://www.datacamp.com/category/python" target="_blank" rel="noopener" class="flex items-center justify-between gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#fef7e0]"><span>DataCamp · Python</span><span class="font-mono" aria-hidden="true">↗</span></a></li><li><a href="https://www.datacamp.com/category/sql" target="_blank" rel="noopener" class="flex items-center justify-between gap-3 border border-[#dadce0] rounded-lg bg-white px-3 py-2 font-bold hover:bg-[#fef7e0]"><span>DataCamp · SQL</span><span class="font-mono" aria-hidden="true">↗</span></a></li></ul></div>
</section>
<section id="suite" hidden class="grid gap-6 md:grid-cols-3" aria-label="Étapes suivantes">
<a href="{{ route('cours.show') }}#td" class="relative border-4 border-dashed border-black bg-white p-6"><span class="absolute -right-3 -top-4 border border-[#dadce0] rounded-lg bg-[#eef0fd] px-2 text-sm font-extrabold">Optionnel</span><p class="font-mono text-sm font-semibold">Étape 3</p><p class="mt-2 text-2xl font-extrabold">TD corrigé</p><p class="mt-2 font-semibold">3 exercices pour s’entraîner.</p></a>
<a href="{{ route('labs.essai') }}" class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-6"><p class="font-mono text-sm font-semibold">Étape 4</p><p class="mt-2 text-2xl font-extrabold">TP sur VM</p><p class="mt-2 font-semibold">Deux VM, un routeur, 45 min.</p></a>
<a href="{{ route('examen') }}" class="border border-[#e3e5e8] rounded-2xl bg-black p-6 text-white"><p class="font-mono text-sm font-semibold">Étape 5</p><p class="mt-2 text-2xl font-extrabold">Examen</p><p class="mt-2 font-semibold">Quand ton prof le programme.</p></a>
</section>
</article>
</div>
<script>
(function () {
var debut = Date.now(), vues = {}, total = 8, MIN = 300, force = false;
var chrono = document.getElementById('chrono'), pct = document.getElementById('pct'), barre = document.getElementById('barre-lecture');
var verrou = document.getElementById('verrou'), vt = document.getElementById('verrou-texte'), form = document.getElementById('form-lecture');
function s() { return Math.floor((Date.now() - debut) / 1000); }
function maj() {
var t = s(), n = Object.keys(vues).length;
chrono.textContent = String(Math.floor(t / 60)).padStart(2, '0') + ':' + String(t % 60).padStart(2, '0');
var p = Math.round(n / total * 100); pct.textContent = p; barre.style.width = p + '%';
vt.textContent = 'Parties lues : ' + n + ' / ' + total + ' · Temps : ' + Math.min(5, Math.floor(t / 60)) + ' / 5 min';
if (force || (n === total && t >= MIN)) { verrou.hidden = true; form.hidden = false; }
}
var io = new IntersectionObserver(function (es) {
es.forEach(function (e) {
if (e.isIntersecting && e.intersectionRatio > 0.35) {
vues[e.target.id] = true;
var a = document.querySelector('[data-lien="' + e.target.id + '"]');
if (a) { a.classList.add('bg-[#e6f4ea]'); a.querySelector('[data-coche]').textContent = '✓'; a.querySelector('[data-coche]').classList.add('bg-black', 'text-white'); }
}
});
maj();
}, { threshold: [0.35] });
document.querySelectorAll('[data-partie]').forEach(function (el) { io.observe(el); });
document.getElementById('debloquer').addEventListener('click', function () { force = true; maj(); });
setInterval(maj, 1000); maj();
})();
(function () {
var form = document.getElementById('form-lecture'), score = document.getElementById('score-lecture');
form.addEventListener('submit', function (e) {
e.preventDefault();
var bons = 0, total = 0;
form.querySelectorAll('[data-q]').forEach(function (q) {
total++;
var choix = q.querySelector('input:checked'), ok = choix && choix.value === q.dataset.ok, c = q.querySelector('[data-correction]');
if (ok) bons++;
c.hidden = false; c.className = 'mt-4 border border-[#dadce0] rounded-lg p-4 ' + (ok ? 'bg-[#e6f4ea]' : 'bg-[#FFD9E8]');
q.querySelector('[data-verdict]').textContent = ok ? 'Bonne réponse.' : (choix ? 'Pas tout à fait.' : 'Pas de réponse.');
q.querySelectorAll('label').forEach(function (l, i) { var b = String(i) === q.dataset.ok; l.classList.toggle('outline', b); l.classList.toggle('outline-4', b); l.classList.toggle('outline-black', b); });
});
score.hidden = false; score.textContent = bons + ' / ' + total;
document.getElementById('suite').hidden = false;
});
})();
(function () {
var cadre = document.getElementById('v-cadre'), cle = 'paillasse-video-' + location.pathname;
function montrer(u) {
var m = String(u).match(/(?:youtu\.be\/|v=|embed\/|shorts\/)([\w-]{11})/); if (!m) return false;
cadre.innerHTML = '<iframe class="h-full w-full" src="https://www.youtube-nocookie.com/embed/' + m[1] + '" title="Vidéo de contexte" allow="accelerometer; encrypted-media; picture-in-picture" allowfullscreen></iframe>';
return true;
}
var s = localStorage.getItem(cle); if (s) montrer(s);
document.getElementById('v-form').addEventListener('submit', function (e) { e.preventDefault(); var u = document.getElementById('v-url').value; if (montrer(u)) localStorage.setItem(cle, u); else alert('Lien YouTube non reconnu.'); });
})();
</script>
@endsection

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,41 @@
@extends('layouts.vitrine')
@section('titre', 'Cours gratuits')
@section('contenu')
<section style="padding:112px 20px 96px;background:#fff"><div style="max-width:900px;margin:0 auto"><p style="margin:0;font-size:15px;font-weight:700;color:#0b57d0;text-align:center">Gratuit, sans compte</p><h1 style="margin:20px 0 0;font-size:clamp(40px,6vw,72px);line-height:1.04;font-weight:800;letter-spacing:-0.03em;color:#0b1220;text-align:center;text-wrap:balance">99 cours gratuits, calés sur vos référentiels.</h1><p style="margin:24px auto 0;max-width:660px;font-size:20px;line-height:1.6;font-weight:500;color:#3c4043;text-align:center;text-wrap:pretty">Chaque cours suit le découpage de l’Éducation nationale : un CM pour comprendre, un TD pour s’exercer sur papier, un TP sur une vraie VM, un QCM corrigé et expliqué.</p><p style="margin:28px 0 0;text-align:center;font-size:15px;font-weight:700;color:#5f6368">99 cours · 45 TD · 59 TP sur VM · 98 QCM corrigés</p><div style="margin-top:44px;display:flex;flex-direction:column;align-items:center;gap:14px"><a href="#nsi" style="display:inline-flex;align-items:center;height:56px;padding:0 32px;border-radius:999px;background:#0b57d0;color:#fff;font-size:17px;font-weight:700;text-decoration:none">Choisir mon cursus</a></div><nav aria-label="Cursus" style="margin-top:28px;display:flex;flex-wrap:wrap;justify-content:center;gap:8px 24px"><a href="#nsi" style="font-size:15px;font-weight:700;color:#0b57d0;text-decoration:none">Lycée NSI</a><a href="#sio" style="font-size:15px;font-weight:700;color:#0b57d0;text-decoration:none">BTS SIO SISR</a><a href="#ciel" style="font-size:15px;font-weight:700;color:#0b57d0;text-decoration:none">BTS CIEL</a><a href="#but" style="font-size:15px;font-weight:700;color:#0b57d0;text-decoration:none">BUT R&amp;T</a><a href="#tssr" style="font-size:15px;font-weight:700;color:#0b57d0;text-decoration:none">Titre pro TSSR</a><a href="#prog" style="font-size:15px;font-weight:700;color:#0b57d0;text-decoration:none">Programmation</a></nav></div></section>
<section id="{{ $c['id'] }}" class="scroll-mt-24" style="border-top:1px solid #e3e5e8" aria-labelledby="t-{{ $c['id'] }}">
<div class="mx-auto max-w-7xl px-5 py-16 lg:px-10">
<div class="flex flex-wrap items-end gap-x-8 gap-y-3">
<h2 id="t-{{ $c['id'] }}" class="inline-block {{ $loop->odd ? '' : '' }} border border-[#e3e5e8] rounded-2xl {{ $c['couleur'] }} px-4 py-1 text-5xl font-extrabold tracking-tight sm:text-6xl">{{ $c['nom'] }}</h2>
<p class="text-lg font-semibold">{{ $c['sous_titre'] }} · {{ collect($c['blocs'])->sum(fn ($b) => count($b['cours'])) }} cours</p>
</div>
<div class="mt-12 grid gap-10 lg:grid-cols-2">
@foreach ($c['blocs'] as $b)
<div data-bloc class="border border-[#e3e5e8] rounded-2xl bg-white {{ $loop->even ? '' : '' }}">
<h3 class="border-b border-[#e3e5e8] {{ $c['couleur'] }} px-5 py-3 text-lg font-extrabold">{{ $b['titre'] }}</h3>
<ul class="divide-y divide-[#e3e5e8]">
@foreach ($b['cours'] as $k)
<li data-types="{{ implode(' ', $k['types']) }}"><a href="{{ isset($k['exercice']) ? route('ide', ['ex' => $k['exercice']]) : route('cours.fiche', ['chapitre' => $k['titre'] ?? '']) }}" class="flex flex-wrap items-center gap-x-4 gap-y-2 px-5 py-3 hover:bg-[#f8f9fa]"><span class="min-w-0 flex-1 font-extrabold">{{ $k['titre'] }}</span><span class="flex gap-1">@foreach ($k['types'] as $t)<span class="border border-[#dadce0] rounded-lg {{ $fond[$t] }} px-1.5 font-mono text-xs font-semibold">{{ $t }}</span>@endforeach</span><span class="w-10 text-right font-mono text-sm font-semibold">{{ $k['heures'] }} h</span></a></li>
@endforeach
</ul>
</div>
@endforeach
</div>
</div>
</section>
@endforeach
<script>
document.querySelectorAll('[data-filtre]').forEach(function (b) {
b.addEventListener('click', function () {
var f = b.dataset.filtre;
document.querySelectorAll('[data-filtre]').forEach(function (x) { x.setAttribute('aria-pressed', x === b); });
document.querySelectorAll('[data-types]').forEach(function (li) {
li.hidden = f !== 'Tout' && li.dataset.types.split(' ').indexOf(f) === -1;
});
document.querySelectorAll('[data-bloc]').forEach(function (b) { b.hidden = !b.querySelector('[data-types]:not([hidden])'); });
document.querySelectorAll('section[id]').forEach(function (s) { if (s.querySelector('[data-bloc]')) s.hidden = !s.querySelector('[data-bloc]:not([hidden])'); });
});
});
</script>
@endsection

View file

@ -0,0 +1,225 @@
@extends('layouts.vitrine')
@section('titre', 'Adressage IPv4 et sous-réseaux')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-[#e6f4ea]">
<div class="mx-auto max-w-7xl px-5 pb-14 pt-10 lg:px-10">
<nav aria-label="Fil d’Ariane" class="flex flex-wrap gap-2 font-semibold"><a href="{{ route('cours.index') }}" class="underline underline-offset-4">Cours</a><span>/</span><a href="{{ route('cours.index') }}#sio" class="underline underline-offset-4">BTS SIO SISR</a><span>/</span><span>Bloc 2</span></nav>
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="mt-6 max-w-4xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Adressage IPv4 et sous-réseaux</h1></div>
<div class="mt-8 flex flex-wrap gap-3 text-sm font-extrabold">
<span class="border border-[#dadce0] rounded-lg bg-white px-3 py-1">BTS SIO SISR · Bloc 2</span>
<span class="border border-[#dadce0] rounded-lg bg-white px-3 py-1">Aussi : BTS CIEL, BUT R&amp;T S1</span>
<span class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 text-white">4 h</span>
</div>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-10 px-5 py-14 lg:grid-cols-12 lg:px-10">
<nav class="lg:col-span-3" aria-label="Parties du cours">
<ol class="sticky top-6 grid gap-3">
<li><a href="{{ route('cours.cm') }}" class="flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 font-extrabold hover:bg-[#f8f9fa]"><span class="font-mono">1</span> CM · Lire</a></li>
<li><a href="#qcm" class="flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-4 py-3 font-extrabold"><span class="font-mono">2</span> QCM · Valider</a></li>
<li><a href="#td" class="flex items-center gap-3 border-4 border-dashed border-black bg-[#eef0fd] px-4 py-3 font-extrabold"><span class="font-mono">3</span> TD · optionnel</a></li>
<li><a href="#tp" class="flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-4 py-3 font-extrabold"><span class="font-mono">4</span> TP · Pratiquer</a></li>
<li><a href="#exam" class="flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-black px-4 py-3 font-extrabold text-white hover:bg-[#ec3013]"><span class="font-mono">5</span> Examen</a></li>
</ol>
</nav>
<div class="grid gap-20 lg:col-span-9">
<section id="cm" class="scroll-mt-6" aria-labelledby="t-cm">
<h2 id="t-cm" class="text-5xl font-extrabold tracking-tight"><span class="font-mono text-2xl align-middle">1 · CM ·</span> Lire le cours</h2>
<a href="{{ route('cours.cm') }}" class="mt-8 grid gap-6 border border-[#e3e5e8] rounded-2xl bg-white p-7 transition-transform md:grid-cols-[1fr_auto]">
<div>
<p class="text-3xl font-extrabold leading-tight">Adressage IPv4 et sous-réseaux · cours complet</p>
<p class="mt-3 text-lg font-semibold">8 parties illustrées : bits, masque, ET logique, diffusion, découpage, adresses privées. Chronométré, à lire en entier pour débloquer le QCM de lecture.</p>
</div>
<div class="grid content-start gap-2 text-center"><span class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-4 py-2 font-mono text-2xl font-semibold">⏱ Lecture chronométrée</span><span class="font-extrabold">Lire le CM →</span></div>
</a>
</section>
<section id="qcm" class="scroll-mt-6" aria-labelledby="t-qcm">
<div class="flex flex-wrap items-end justify-between gap-4">
<h2 id="t-qcm" class="text-5xl font-extrabold tracking-tight"><span class="font-mono text-2xl align-middle">2 · QCM ·</span> Valider les notions</h2>
<p class="font-semibold">5 questions · correction expliquée</p>
</div>
<form id="qcm-form" class="mt-8 grid gap-6">
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="1">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 1</legend>
<p class="text-xl font-extrabold">Combien d’adresses d’hôtes utilisables dans un réseau /27 ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q0" value="0" class="h-5 w-5 accent-black"><span class="font-mono">32</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q0" value="1" class="h-5 w-5 accent-black"><span class="font-mono">30</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q0" value="2" class="h-5 w-5 accent-black"><span class="font-mono">27</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q0" value="3" class="h-5 w-5 accent-black"><span class="font-mono">62</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4">
<p data-verdict class="font-extrabold"></p>
<p class="mt-1 font-medium">Un /27 laisse 32 − 27 = 5 bits pour les hôtes, soit 2⁵ = 32 adresses. On retire l’adresse du réseau et celle de diffusion : il reste 30 hôtes.</p>
</div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="2">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 2</legend>
<p class="text-xl font-extrabold">Quelle est l’adresse réseau de 10.0.3.200/22 ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q1" value="0" class="h-5 w-5 accent-black"><span class="font-mono">10.0.3.0</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q1" value="1" class="h-5 w-5 accent-black"><span class="font-mono">10.0.2.0</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q1" value="2" class="h-5 w-5 accent-black"><span class="font-mono">10.0.0.0</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q1" value="3" class="h-5 w-5 accent-black"><span class="font-mono">10.0.4.0</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4">
<p data-verdict class="font-extrabold"></p>
<p class="mt-1 font-medium">Le masque /22 vaut 255.255.252.0. Sur le 3ᵉ octet, 3 ET 252 = 0. L’adresse réseau est donc 10.0.0.0, et le réseau va jusqu’à 10.0.3.255.</p>
</div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="1">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 3</legend>
<p class="text-xl font-extrabold">Quel masque correspond à /26 ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q2" value="0" class="h-5 w-5 accent-black"><span class="font-mono">255.255.255.128</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q2" value="1" class="h-5 w-5 accent-black"><span class="font-mono">255.255.255.192</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q2" value="2" class="h-5 w-5 accent-black"><span class="font-mono">255.255.255.224</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q2" value="3" class="h-5 w-5 accent-black"><span class="font-mono">255.255.255.240</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4">
<p data-verdict class="font-extrabold"></p>
<p class="mt-1 font-medium">26 bits = 24 bits (255.255.255) + 2 bits dans le dernier octet. 2 bits à 1 à gauche : 128 + 64 = 192.</p>
</div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="1">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 4</legend>
<p class="text-xl font-extrabold">192.168.1.130/25 et 192.168.1.100/25 sont-ils dans le même réseau ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q3" value="0" class="h-5 w-5 accent-black"><span class="font-mono">Oui</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q3" value="1" class="h-5 w-5 accent-black"><span class="font-mono">Non</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4">
<p data-verdict class="font-extrabold"></p>
<p class="mt-1 font-medium">Avec /25, le dernier octet se coupe en deux blocs : 0 à 127 et 128 à 255. 100 est dans le premier, 130 dans le second. Il faut un routeur pour qu’ils communiquent.</p>
</div>
</fieldset>
<fieldset class="border border-[#e3e5e8] rounded-2xl bg-white p-5" data-q data-ok="1">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 5</legend>
<p class="text-xl font-extrabold">Quelle commande affiche les adresses IP sous Debian ?</p>
<div class="mt-4 grid gap-2 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q4" value="0" class="h-5 w-5 accent-black"><span class="font-mono">ipconfig</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q4" value="1" class="h-5 w-5 accent-black"><span class="font-mono">ip addr</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q4" value="2" class="h-5 w-5 accent-black"><span class="font-mono">ifconfig /all</span></label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q4" value="3" class="h-5 w-5 accent-black"><span class="font-mono">netstat -r</span></label>
</div>
<div data-correction hidden class="mt-4 border border-[#dadce0] rounded-lg p-4">
<p data-verdict class="font-extrabold"></p>
<p class="mt-1 font-medium">ip addr (ou ip a) fait partie d’iproute2, installé par défaut. ipconfig est une commande Windows, et ifconfig vient de net-tools, qui n’est plus installé par défaut.</p>
</div>
</fieldset>
<div class="flex flex-wrap items-center gap-5">
<button type="submit" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013].5.5 active:shadow-none">Corriger mon QCM</button>
<button type="reset" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold transition-transform hover:bg-[#fef7e0] active:shadow-none">Recommencer</button>
<p id="qcm-score" class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-4 py-2 text-2xl font-extrabold" hidden></p>
</div>
</form>
</section>
<section id="td" class="scroll-mt-6" aria-labelledby="t-td">
<h2 id="t-td" class="text-5xl font-extrabold tracking-tight"><span class="font-mono text-2xl align-middle">3 · TD ·</span> S’exercer <span class="ml-2 inline-block border border-[#dadce0] rounded-lg bg-[#eef0fd] px-2 align-middle text-base">optionnel</span></h2>
<ol class="mt-8 grid gap-6">
<li class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-6">
<p class="font-mono text-sm font-semibold">Exercice 1</p>
<p class="mt-2 text-xl font-extrabold">Pour 172.16.5.130/25, donnez l’adresse réseau, la diffusion et le nombre d’hôtes.</p>
<details class="mt-4 border border-[#dadce0] rounded-lg bg-white">
<summary class="cursor-pointer px-4 py-2 font-extrabold">Voir la correction expliquée</summary>
<p class="border-t border-[#e3e5e8] px-4 py-3 font-medium">Un /25 coupe le dernier octet en blocs de 128. 130 est dans le bloc 128–255. Réseau : 172.16.5.128. Diffusion : 172.16.5.255. Hôtes : 2⁷ − 2 = 126.</p>
</details>
</li>
<li class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-6 md:ml-10">
<p class="font-mono text-sm font-semibold">Exercice 2</p>
<p class="mt-2 text-xl font-extrabold">Découpez 192.168.1.0/24 en 4 sous-réseaux de même taille.</p>
<details class="mt-4 border border-[#dadce0] rounded-lg bg-white">
<summary class="cursor-pointer px-4 py-2 font-extrabold">Voir la correction expliquée</summary>
<p class="border-t border-[#e3e5e8] px-4 py-3 font-medium">4 sous-réseaux = 2 bits empruntés, donc /26. Sous-réseaux : 192.168.1.0, .64, .128 et .192, avec 62 hôtes chacun.</p>
</details>
</li>
<li class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-6">
<p class="font-mono text-sm font-semibold">Exercice 3</p>
<p class="mt-2 text-xl font-extrabold">Le service comptabilité a 50 postes. Quel est le plus petit sous-réseau qui convient ?</p>
<details class="mt-4 border border-[#dadce0] rounded-lg bg-white">
<summary class="cursor-pointer px-4 py-2 font-extrabold">Voir la correction expliquée</summary>
<p class="border-t border-[#e3e5e8] px-4 py-3 font-medium">Il faut 2ʰ − 2 ≥ 50. Avec h = 6 : 64 − 2 = 62. On garde 6 bits d’hôte, soit un /26 (255.255.255.192). Un /27 ne donnerait que 30 hôtes.</p>
</details>
</li>
</ol>
</section>
<section id="tp" class="scroll-mt-6" aria-labelledby="t-tp">
<h2 id="t-tp" class="text-5xl font-extrabold tracking-tight"><span class="font-mono text-2xl align-middle">4 · TP ·</span> Pratiquer sur VM</h2>
<div class="mt-8 grid gap-8 md:grid-cols-2">
<div class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-6">
<h3 class="text-2xl font-extrabold">Deux VM, un routeur</h3>
<ol class="mt-4 grid gap-2 font-semibold">
<li>1. Placez deux VM dans 192.168.10.0/26.</li>
<li>2. Vérifiez qu’elles se joignent avec ping.</li>
<li>3. Passez la seconde en 192.168.10.70/26.</li>
<li>4. Constatez l’échec, puis ajoutez une route.</li>
</ol>
<p class="mt-4 font-mono text-sm font-semibold">4 étapes vérifiées automatiquement · 45 min</p>
<a href="{{ route('labs.essai') }}" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013].5.5 active:shadow-none mt-6">Lancer le TP <span class="font-mono" aria-hidden="true">→</span></a>
</div>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#13233A] p-5 font-mono text-sm text-white">
<p><span class="text-[#7CF2C0]">eleve@vm1</span>:~$ sudo ip addr add 192.168.10.10/26 dev ens3</p>
<p><span class="text-[#7CF2C0]">eleve@vm1</span>:~$ ip -br addr</p>
<p>ens3 UP 192.168.10.10/26</p>
<p><span class="text-[#7CF2C0]">eleve@vm1</span>:~$ ping -c 1 192.168.10.11</p>
<p>1 packets transmitted, 1 received</p>
<p class="mt-2 text-[#FFD23F]">✓ Étape 2 validée</p>
</div>
</div>
</section>
<section id="exam" class="scroll-mt-6" aria-labelledby="t-exam">
<h2 id="t-exam" class="text-5xl font-extrabold tracking-tight"><span class="font-mono text-2xl align-middle">5 · EXAMEN ·</span> Quand le prof le décide</h2>
<div class="mt-8 grid gap-6 border border-[#e3e5e8] rounded-2xl bg-black p-7 text-white md:grid-cols-[1fr_auto]">
<p class="text-xl font-bold">Le prof compose son sujet dans la banque de questions, le programme pour la classe, et suit l’épreuve en direct : sorties d’onglet, copier-coller bloqué, remise automatique.</p>
<div class="grid content-start gap-3"><a href="{{ route('examen') }}" class="border-4 border-white bg-[#ec3013] px-5 py-3 font-extrabold">Voir le mode examen</a><a href="{{ route('banque') }}" class="border-4 border-white bg-white px-5 py-3 font-extrabold text-black hover:bg-[#fef7e0]">Banque de sujets (profs)</a></div>
</div>
</section>
</div>
</div>
<script>
(function () {
var form = document.getElementById('qcm-form');
var score = document.getElementById('qcm-score');
form.addEventListener('submit', function (e) {
e.preventDefault();
var bons = 0, total = 0;
form.querySelectorAll('[data-q]').forEach(function (q) {
total++;
var choix = q.querySelector('input:checked');
var ok = choix && choix.value === q.dataset.ok;
if (ok) bons++;
var c = q.querySelector('[data-correction]');
c.hidden = false;
c.className = 'mt-4 border border-[#dadce0] rounded-lg p-4 ' + (ok ? 'bg-[#e6f4ea]' : 'bg-[#FFD9E8]');
q.querySelector('[data-verdict]').textContent = ok ? 'Bonne réponse.' : (choix ? 'Pas tout à fait.' : 'Pas de réponse.');
q.querySelectorAll('label').forEach(function (l, i) {
l.classList.toggle('outline', String(i) === q.dataset.ok);
l.classList.toggle('outline-4', String(i) === q.dataset.ok);
l.classList.toggle('outline-black', String(i) === q.dataset.ok);
});
});
score.hidden = false;
score.textContent = bons + ' / ' + total;
});
form.addEventListener('reset', function () {
form.querySelectorAll('[data-correction]').forEach(function (c) { c.hidden = true; });
form.querySelectorAll('label').forEach(function (l) { l.classList.remove('outline', 'outline-4', 'outline-black'); });
score.hidden = true;
});
})();
</script>
@endsection

View file

@ -0,0 +1,65 @@
@extends('layouts.vitrine')
@section('titre', 'Devoirs maison')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-end gap-6 px-5 pb-10 pt-10 lg:px-10">
<div class="flex-1"><p class="font-mono text-sm font-semibold">Espace enseignant · Devoirs</p><div class="min-w-0 flex-1"><p data-public="P" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#1d3fa8]">Pour les profs</p>
<h1 class="mt-2 text-5xl font-extrabold leading-[0.95] tracking-tight sm:text-6xl">Devoirs maison</h1></div><p class="mt-3 max-w-2xl text-lg font-semibold">Donnez un TP, un QCM, un TD ou un exercice de code à faire à la maison. Programmez l’ouverture et la date limite, suivez les rendus, corrigez et notez.</p></div>
<a href="#nouveau" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white hover:bg-[#ec3013]">+ Nouveau devoir</a>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-10 px-5 py-12 lg:grid-cols-12 lg:px-10">
<section class="lg:col-span-7" aria-labelledby="t-liste">
<h2 id="t-liste" class="text-3xl font-extrabold">Devoirs programmés</h2>
<ul id="liste-devoirs" class="mt-6 grid gap-5">
<li class="border border-[#e3e5e8] rounded-2xl bg-white p-5"><div class="flex flex-wrap items-center gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">TP sur VM</span><span class="border border-[#dadce0] rounded-lg px-2">BTS SIO 1 · A</span><span class="ml-auto font-mono">⏰ Ven. 3 oct. · 23:59</span></div><p class="mt-3 text-xl font-extrabold">TP Routage inter-VLAN</p><div class="mt-3 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full border-r border-[#e3e5e8] bg-black" style="width:75%"></div></div><p class="mt-2 font-mono text-sm font-semibold">18 / 24 rendus · <span class="bg-[#ec3013] px-1 text-white">2 en retard</span></p></li>
<li class="border border-[#e3e5e8] rounded-2xl bg-white p-5"><div class="flex flex-wrap items-center gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2">QCM</span><span class="border border-[#dadce0] rounded-lg px-2">BTS SIO 1 · A</span><span class="ml-auto font-mono">⏰ Lun. 6 oct. · 08:00</span></div><p class="mt-3 text-xl font-extrabold">QCM Adressage IPv4 · 2ᵉ essai</p><div class="mt-3 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full border-r border-[#e3e5e8] bg-black" style="width:46%"></div></div><p class="mt-2 font-mono text-sm font-semibold">11 / 24 rendus</p></li>
<li class="border border-[#e3e5e8] rounded-2xl bg-white p-5"><div class="flex flex-wrap items-center gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#fce8e6] px-2">IDE</span><span class="border border-[#dadce0] rounded-lg px-2">2nde NSI · B</span><span class="ml-auto font-mono">⏰ Mer. 8 oct. · 18:00</span></div><p class="mt-3 text-xl font-extrabold">Défi Python : somme d’une liste</p><div class="mt-3 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full border-r border-[#e3e5e8] bg-black" style="width:18%"></div></div><p class="mt-2 font-mono text-sm font-semibold">5 / 28 rendus</p></li>
<li class="border border-[#e3e5e8] rounded-2xl bg-white p-5"><div class="flex flex-wrap items-center gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#eef0fd] px-2">TD</span><span class="border border-[#dadce0] rounded-lg px-2">BTS SIO 1 · A</span><span class="ml-auto font-mono">⏰ Clos · 29 sept.</span></div><p class="mt-3 text-xl font-extrabold">TD Découpage en sous-réseaux</p><div class="mt-3 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full border-r border-[#e3e5e8] bg-black" style="width:100%"></div></div><p class="mt-2 font-mono text-sm font-semibold">24 / 24 rendus · <span class="bg-[#ec3013] px-1 text-white">3 en retard</span></p></li>
</ul>
</section>
<section class="lg:col-span-5" aria-labelledby="t-rendus">
<div class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-6">
<h2 id="t-rendus" class="text-2xl font-extrabold">Rendus · TD Découpage en sous-réseaux</h2>
<table class="mt-4 w-full border border-[#e3e5e8] rounded-2xl bg-white text-left text-sm"><thead class="bg-[#0b57d0] text-white"><tr><th class="px-3 py-2">Élève</th><th class="px-3 py-2">État</th><th class="px-3 py-2">Note</th></tr></thead><tbody class="divide-y divide-[#e3e5e8]">
<tr><td class="px-3 py-2"><span class="block font-extrabold">Léa M.</span><span class="font-mono text-xs">30 sept. · 17:42</span></td><td class="px-3 py-2"><span class="border border-[#dadce0] rounded-lg px-1.5 text-xs font-extrabold bg-[#e6f4ea]">Rendu</span></td><td class="px-3 py-2 font-mono font-semibold">18/20</td></tr>
<tr><td class="px-3 py-2"><span class="block font-extrabold">Yanis B.</span><span class="font-mono text-xs">1 oct. · 22:10</span></td><td class="px-3 py-2"><span class="border border-[#dadce0] rounded-lg px-1.5 text-xs font-extrabold bg-[#e6f4ea]">Rendu</span></td><td class="px-3 py-2 font-mono font-semibold">14/20</td></tr>
<tr><td class="px-3 py-2"><span class="block font-extrabold">Nora Kaci</span><span class="font-mono text-xs">2 oct. · 09:05</span></td><td class="px-3 py-2"><span class="border border-[#dadce0] rounded-lg px-1.5 text-xs font-extrabold bg-[#fef7e0]">En retard</span></td><td class="px-3 py-2 font-mono font-semibold">—</td></tr>
<tr><td class="px-3 py-2"><span class="block font-extrabold">Sami L.</span><span class="font-mono text-xs">—</span></td><td class="px-3 py-2"><span class="border border-[#dadce0] rounded-lg px-1.5 text-xs font-extrabold bg-[#ec3013] text-white">Non rendu</span></td><td class="px-3 py-2 font-mono font-semibold">—</td></tr>
<tr><td class="px-3 py-2"><span class="block font-extrabold">Chloé P.</span><span class="font-mono text-xs">29 sept. · 20:31</span></td><td class="px-3 py-2"><span class="border border-[#dadce0] rounded-lg px-1.5 text-xs font-extrabold bg-[#e6f4ea]">Rendu</span></td><td class="px-3 py-2 font-mono font-semibold">19/20</td></tr>
</tbody></table>
<div class="mt-4 flex flex-wrap gap-3"><button type="button" class="border border-[#e3e5e8] rounded-2xl bg-black px-4 py-2 font-extrabold text-white">Relancer les non-rendus</button><button type="button" class="border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2 font-extrabold hover:bg-[#fef7e0]">Exporter les notes</button></div>
</div>
</section>
</div>
<section id="nouveau" class="scroll-mt-6 border-t border-[#e3e5e8] bg-[#fef7e0]" aria-labelledby="t-nouveau">
<div class="mx-auto max-w-7xl px-5 py-14 lg:px-10">
<h2 id="t-nouveau" class="text-4xl font-extrabold tracking-tight">Programmer un devoir</h2>
<form id="f-devoir" class="mt-8 grid gap-5 border border-[#e3e5e8] rounded-2xl bg-white p-7 md:grid-cols-2">
<label class="grid gap-2 font-extrabold md:col-span-2">Titre<input id="d-titre" required value="TP Serveur web Apache" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black focus:bg-[#f8f9fa] focus:outline-none"></label>
<label class="grid gap-2 font-extrabold">Activité<select id="d-type" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black focus:bg-[#f8f9fa] focus:outline-none"><option>TP sur VM</option><option>Lab web (terminal + navigateur)</option><option>QCM</option><option>TD</option><option>IDE</option><option>Générateur de TD</option><option>Rendu de fichier</option></select></label>
<label class="grid gap-2 font-extrabold">Classe<select id="d-classe" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black focus:bg-[#f8f9fa] focus:outline-none"><option>BTS SIO 1 · A</option><option>2nde NSI · B</option><option>BUT R&amp;T 1</option></select></label>
<label class="grid gap-2 font-extrabold">Ouverture<input type="datetime-local" value="2026-10-01T08:00" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black focus:bg-[#f8f9fa] focus:outline-none font-mono"></label>
<label class="grid gap-2 font-extrabold">Date limite<input id="d-lim" type="datetime-local" value="2026-10-10T23:59" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black focus:bg-[#f8f9fa] focus:outline-none font-mono"></label>
<fieldset class="grid gap-2 font-semibold md:col-span-2"><legend class="font-extrabold">Options</legend>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Accepter les rendus en retard (signalés)</label>
<label class="flex items-center gap-3"><input type="checkbox" checked class="h-5 w-5 accent-black"> Correction automatique, visible après la date limite</label>
<label class="flex items-center gap-3"><input type="checkbox" class="h-5 w-5 accent-black"> Rappel aux élèves la veille</label>
</fieldset>
<div class="flex flex-wrap items-center gap-4 md:col-span-2"><button type="submit" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white hover:bg-[#ec3013]">Programmer le devoir</button><a href="{{ route('bibliotheque') }}" class="font-extrabold underline underline-offset-4">Choisir dans la bibliothèque</a><p id="d-ok" hidden class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-4 py-2 font-extrabold">Devoir programmé ✓</p></div>
</form>
</div>
</section>
<script>
document.getElementById('f-devoir').addEventListener('submit', function (e) {
e.preventDefault();
var li = document.createElement('li'), lim = new Date(document.getElementById('d-lim').value);
li.className = 'border border-[#e3e5e8] rounded-2xl bg-white p-5 outline outline-4 outline-[#7CF2C0]';
li.innerHTML = '<div class="flex flex-wrap items-center gap-2 text-xs font-extrabold"><span class="border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-2">' + document.getElementById('d-type').value + '</span><span class="border border-[#dadce0] rounded-lg px-2">' + document.getElementById('d-classe').value + '</span><span class="ml-auto font-mono">⏰ ' + lim.toLocaleString('fr-FR', { dateStyle: 'short', timeStyle: 'short' }) + '</span></div><p class="mt-3 text-xl font-extrabold"></p><p class="mt-2 font-mono text-sm font-semibold">0 rendu · ouverture programmée</p>';
li.querySelector('p').textContent = document.getElementById('d-titre').value;
document.getElementById('liste-devoirs').prepend(li); document.getElementById('d-ok').hidden = false;
});
</script>
@endsection

View file

@ -0,0 +1,65 @@
@extends('layouts.vitrine')
@section('titre', 'Espace élève')
@section('contenu')
<section class="relative overflow-hidden border-b border-[#e3e5e8] bg-white">
<div aria-hidden="true" class="pointer-events-none absolute inset-0"></div>
<div class="relative mx-auto flex max-w-7xl flex-wrap items-end gap-6 px-5 pb-12 pt-12 lg:px-10">
<div class="flex-1">
<p class="font-mono text-sm font-semibold">Espace élève · {{ $eleve->identifiant }}</p>
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="mt-2 text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Salut {{ $eleve->prenom }}.</h1></div>
<p class="mt-4 text-xl font-semibold">{{ $eleve->classe->nom }}@if($eleve->classe->formation) · {{ $eleve->classe->formation }}@endif</p>
</div>
<a href="{{ route('labs.essai') }}" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013].5.5 active:shadow-none">Reprendre mon TP <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-12 px-5 py-14 lg:grid-cols-12 lg:px-10">
<section class="lg:col-span-7" aria-labelledby="t-afaire">
<h2 id="t-afaire" class="text-4xl font-extrabold tracking-tight">À faire</h2>
<ul class="mt-8 grid gap-6">
<li><a href="{{ route('ide') }}" class="relative flex flex-wrap items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-white p-5"><span class="absolute -right-3 -top-4 border border-[#dadce0] rounded-lg bg-[#ec3013] px-2 py-0.5 text-sm font-extrabold text-white">Devoir maison</span><span class="border border-[#dadce0] rounded-lg bg-[#13233A] px-2 font-mono text-sm font-semibold text-white">IDE</span><span class="flex-1"><span class="block text-xl font-extrabold">Défi Python : somme d’une liste</span><span class="block font-semibold">À rendre mer. 8 oct. · 18:00</span></span><span class="font-mono font-semibold">Rendre →</span></a></li>
<li><a href="{{ route('labs.essai') }}" class="relative flex flex-wrap items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-5 transition-transform">
<span class="absolute -right-3 -top-4 border border-[#dadce0] rounded-lg bg-white px-2 py-0.5 text-sm font-extrabold">En cours</span>
<span class="border border-[#dadce0] rounded-lg bg-white px-2 font-mono text-sm font-semibold">TP</span>
<span class="flex-1"><span class="block text-xl font-extrabold">Routage inter-VLAN</span><span class="block font-semibold">Étape 3 sur 4 · VM prête</span></span>
<span class="font-mono font-semibold">Continuer →</span></a></li>
<li><a href="{{ route('cours.show') }}#qcm" class="flex flex-wrap items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-5 transition-transform md:ml-8">
<span class="border border-[#dadce0] rounded-lg bg-white px-2 font-mono text-sm font-semibold">QCM</span>
<span class="flex-1"><span class="block text-xl font-extrabold">Adressage IPv4 · 2ᵉ essai</span><span class="block font-semibold">Pour vendredi · 5 questions</span></span>
<span class="font-mono font-semibold">Commencer →</span></a></li>
<li><a href="{{ route('cours.show') }}#td" class="flex flex-wrap items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-5 transition-transform">
<span class="border border-[#dadce0] rounded-lg bg-white px-2 font-mono text-sm font-semibold">TD</span>
<span class="flex-1"><span class="block text-xl font-extrabold">Découpage en sous-réseaux</span><span class="block font-semibold">Assigné par Mme Roux · 3 exercices</span></span>
<span class="font-mono font-semibold">Ouvrir →</span></a></li>
<li><a href="{{ route('examen') }}" class="flex flex-wrap items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black p-5 text-white transition-transform md:ml-8">
<span class="border-2 border-white bg-[#ec3013] px-2 font-mono text-sm font-semibold">EXAMEN</span>
<span class="flex-1"><span class="block text-xl font-extrabold">E6 blanc SISR · Adressage et VLAN</span><span class="block font-semibold">Lundi 10:00 · 1 h</span></span>
<span class="font-mono font-semibold">Voir →</span></a></li>
</ul>
</section>
<aside class="grid content-start gap-10 lg:col-span-5">
<section class="border border-[#e3e5e8] rounded-2xl bg-white p-6" aria-labelledby="t-prog">
<h2 id="t-prog" class="text-2xl font-extrabold">Ma progression</h2>
<ul class="mt-5 grid gap-4">
<li><p class="flex justify-between font-bold"><span>Adressage IPv4</span><span class="font-mono">100 %</span></p><div class="mt-1 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full bg-[#e6f4ea] border-r border-[#e3e5e8]" style="width:100%"></div></div></li>
<li><p class="flex justify-between font-bold"><span>VLAN et commutation</span><span class="font-mono">100 %</span></p><div class="mt-1 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full bg-[#e6f4ea] border-r border-[#e3e5e8]" style="width:100%"></div></div></li>
<li><p class="flex justify-between font-bold"><span>Routage inter-VLAN</span><span class="font-mono">75 %</span></p><div class="mt-1 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full bg-[#fef7e0] border-r border-[#e3e5e8]" style="width:75%"></div></div></li>
<li><p class="flex justify-between font-bold"><span>Serveur DHCP</span><span class="font-mono">25 %</span></p><div class="mt-1 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full bg-[#fef7e0] border-r border-[#e3e5e8]" style="width:25%"></div></div></li>
<li><p class="flex justify-between font-bold"><span>Serveur DNS avec BIND 9</span><span class="font-mono">0 %</span></p><div class="mt-1 h-4 border border-[#dadce0] rounded-lg bg-white"><div class="h-full bg-white border-r border-[#e3e5e8]" style="width:0%"></div></div></li>
</ul>
</section>
<section class="border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] p-6" aria-labelledby="t-notes">
<h2 id="t-notes" class="text-2xl font-extrabold">Mes QCM</h2>
<ul class="mt-4 divide-y divide-[#e3e5e8] border border-[#dadce0] rounded-lg bg-white font-semibold">
<li class="flex justify-between px-4 py-2"><span>VLAN et commutation</span><span class="font-mono">17/20</span></li>
<li class="flex justify-between px-4 py-2"><span>Adressage IPv4</span><span class="font-mono">14/20</span></li>
<li class="flex justify-between px-4 py-2"><span>Modèle OSI</span><span class="font-mono">18/20</span></li>
</ul>
<a href="{{ route('cours.index') }}" class="mt-5 inline-block border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2 font-extrabold hover:bg-[#fef7e0]">Réviser dans les cours</a>
<a href="{{ route('maison') }}" class="mt-3 block font-extrabold underline underline-offset-4">Aller plus loin à la maison →</a>
</section>
</aside>
</div>
@endsection

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mode examen · Syllabus</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@500;700;800;900&family=IBM+Plex+Mono:wght@400;600&display=swap" rel="stylesheet">
@vite(['resources/css/app.css', 'resources/js/app.js'])
<style>
.etoile { clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); }
.zigzag { background: linear-gradient(135deg, transparent 50%, #000 50% 62%, transparent 62%) 0 0 / 16px 16px, linear-gradient(45deg, transparent 50%, #000 50% 62%, transparent 62%) 0 0 / 16px 16px; }
@keyframes flotte { 0%,100% { transform: translateY(0) rotate(var(--r, 0deg)); } 50% { transform: translateY(-10px) rotate(var(--r, 0deg)); } }
.flotte { animation: flotte 6s ease-in-out infinite; }
@keyframes clignote { 50% { opacity: 0; } }
.curseur { animation: clignote 1s steps(1) infinite; }
@media (prefers-reduced-motion: reduce) { .flotte, .curseur { animation: none; } }
</style>
<link rel="stylesheet" href="{{ asset('css/syllabus-theme.css') }}">
</head>
<body class="bg-white font-display text-black antialiased">
<header class="border-b-4 border-black bg-black text-white">
<div class="mx-auto flex max-w-7xl flex-wrap items-center gap-x-6 gap-y-3 px-5 py-4 lg:px-10">
<span class="border-2 border-white bg-[#ec3013] px-3 py-1 font-extrabold">MODE EXAMEN</span>
<p class="flex-1 font-bold">Adressage et VLAN · E6 blanc SISR · Léa M.</p>
<p class="flex items-center gap-3"><span class="font-semibold">Temps restant</span><span id="chrono" class="border-2 border-white bg-[#FFD23F] px-3 py-1 font-mono text-2xl font-semibold text-black" role="timer" aria-live="off">59:59</span></p>
</div>
</header>
<div class="border-b border-[#e3e5e8] bg-[#fef7e0]">
<ul class="mx-auto flex max-w-7xl flex-wrap gap-x-6 gap-y-1 px-5 py-2 text-sm font-extrabold lg:px-10">
<li>■ Indices désactivés</li><li>■ Copier-coller bloqué</li><li>■ Sortie d’onglet signalée à l’enseignant</li><li>■ VM sans accès Internet</li><li class="ml-auto">Incidents signalés : <span id="incidents" class="font-mono">0</span></li>
</ul>
</div>
<main class="mx-auto grid max-w-7xl gap-10 px-5 py-10 lg:grid-cols-12 lg:px-10">
<nav class="lg:col-span-3" aria-label="Questions">
<h2 class="text-xl font-extrabold">Questions</h2>
<ol class="mt-4 grid grid-cols-5 gap-2 lg:grid-cols-4">
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-[#0b57d0] text-white">1</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-[#0b57d0] text-white">2</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-[#0b57d0] text-white">3</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-[#0b57d0] text-white">4</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-[#fef7e0]" aria-current="step">5</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-white">6</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-white">7</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-[#fce8e6]">8</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-white">9</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-white">10</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-white">11</a></li>
<li><a href="#q" class="grid h-11 place-items-center border border-[#dadce0] rounded-lg font-mono font-semibold bg-white">12</a></li>
</ol>
<ul class="mt-5 grid gap-1 text-sm font-semibold">
<li class="flex items-center gap-2"><span class="h-3 w-3 bg-black"></span> Répondue</li>
<li class="flex items-center gap-2"><span class="h-3 w-3 border border-[#dadce0] rounded-lg bg-[#fce8e6]"></span> Marquée pour revoir</li>
</ul>
<p class="mt-6 border border-[#dadce0] rounded-lg p-3 font-mono text-sm font-semibold">4 / 12 répondues · Partie TP : 0 / 3 étapes</p>
</nav>
<div class="grid gap-10 lg:col-span-9">
<fieldset id="q" class="border border-[#e3e5e8] rounded-2xl bg-white p-6">
<legend class="-ml-2 border border-[#dadce0] rounded-lg bg-[#fef7e0] px-2 font-mono text-sm font-semibold">Question 5 · 1 point</legend>
<p class="text-2xl font-extrabold">Un service de 50 postes doit avoir son propre sous-réseau. Quel masque choisissez-vous ?</p>
<div class="mt-5 grid gap-3 sm:grid-cols-2">
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-mono font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q5" class="h-5 w-5 accent-black"> /24 · 255.255.255.0</label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-mono font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q5" class="h-5 w-5 accent-black"> /25 · 255.255.255.128</label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-mono font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q5" class="h-5 w-5 accent-black"> /26 · 255.255.255.192</label>
<label class="flex cursor-pointer items-center gap-3 border border-[#dadce0] rounded-lg px-4 py-3 font-mono font-semibold hover:bg-[#f8f9fa] has-[:checked]:bg-[#eef0fd]"><input type="radio" name="q5" class="h-5 w-5 accent-black"> /27 · 255.255.255.224</label>
</div>
<div class="mt-6 flex flex-wrap gap-3">
<a href="#q" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold transition-transform hover:bg-[#fef7e0] active:shadow-none">← Précédente</a>
<button type="button" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold transition-transform hover:bg-[#fef7e0] active:shadow-none">Marquer pour revoir</button>
<a href="#q" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold transition-transform hover:bg-[#fef7e0] active:shadow-none bg-[#0b57d0] text-white hover:text-black">Suivante →</a>
</div>
</fieldset>
<section class="border border-[#e3e5e8] rounded-2xl bg-[#13233A] font-mono text-white" aria-labelledby="t-partie">
<div class="flex flex-wrap items-center gap-3 border-b border-[#e3e5e8] bg-[#0d192b] px-4 py-2">
<h2 id="t-partie" class="flex-1 text-sm font-semibold">Partie TP · commutateur-sw1 · console 1</h2>
<span class="border-2 border-white px-2 text-xs">vérification à la remise</span>
</div>
<div class="space-y-1 p-5 text-sm leading-relaxed">
<p class="text-[#FFD23F]">Créez le VLAN 20 « compta » et placez-y l’interface eth2.</p>
<p><span class="text-[#7CF2C0]">root@sw1</span>:~# ip link add link eth0 name eth0.20 type vlan id 20</p>
<p><span class="text-[#7CF2C0]">root@sw1</span>:~# <span class="curseur inline-block h-4 w-2.5 translate-y-0.5 bg-[#fef7e0]"></span></p>
</div>
</section>
<div class="flex flex-wrap items-center gap-5">
<button type="button" id="rendre" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013].5.5 active:shadow-none">Rendre ma copie</button>
<p class="font-semibold">La copie est rendue automatiquement à la fin du temps.</p>
</div>
</div>
</main>
<script>
(function () {
var fin = Date.now() + 60 * 60 * 1000 - 1000;
var el = document.getElementById('chrono');
function tic() {
var s = Math.max(0, Math.round((fin - Date.now()) / 1000));
el.textContent = String(Math.floor(s / 60)).padStart(2, '0') + ':' + String(s % 60).padStart(2, '0');
if (s < 300) el.classList.add('bg-[#ec3013]', 'text-white');
}
tic(); setInterval(tic, 1000);
var inc = 0, spot = document.getElementById('incidents'), last = 0;
function signal() { if (Date.now() - last < 800) return; last = Date.now(); inc++; spot.textContent = inc; spot.parentNode.classList.add('bg-[#ec3013]', 'text-white', 'px-2'); }
document.addEventListener('visibilitychange', function () { if (document.hidden) signal(); });
window.addEventListener('blur', signal);
document.documentElement.addEventListener('mouseleave', signal);
['copy', 'cut', 'paste'].forEach(function (ev) { document.addEventListener(ev, function (e) { e.preventDefault(); signal(); }); });
document.getElementById('rendre').addEventListener('click', function () {
if (confirm('Rendre la copie ? Vous ne pourrez plus la modifier.')) {
this.textContent = 'Copie rendue ✓';
this.disabled = true;
}
});
})();
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,105 @@
@extends('layouts.vitrine')
@section('titre', 'Générateur de TD')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto max-w-7xl px-5 pb-12 pt-12 lg:px-10">
<p class="inline-block border border-[#dadce0] rounded-lg bg-[#fce8e6] px-3 py-1 text-sm font-bold">Générateur de TD</p>
<div class="min-w-0 flex-1"><p data-public="P" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#1d3fa8]">Pour les profs</p>
<h1 class="mt-6 max-w-5xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Des exercices à l’infini, corrigés tout de suite.</h1></div>
<p class="mt-6 max-w-3xl text-xl font-medium leading-relaxed">Chaque clic tire un nouvel exercice au hasard. La correction montre le calcul, étape par étape. En mode examen : 10 questions, chronométrées, notées sur 20.</p>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-10 px-5 py-12 lg:grid-cols-12 lg:px-10">
<aside class="grid content-start gap-4 lg:col-span-3">
<p class="font-extrabold">Type d’exercice</p>
<div class="grid gap-2" role="group" aria-label="Type d’exercice">
<button type="button" data-type="reseau" aria-pressed="true" class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-4 py-3 text-left font-extrabold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-2 aria-pressed:outline-black">Sous-réseaux</button>
<button type="button" data-type="binaire" aria-pressed="false" class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-4 py-3 text-left font-extrabold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-2 aria-pressed:outline-black">Décimal → binaire</button>
<button type="button" data-type="hexa" aria-pressed="false" class="border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] px-4 py-3 text-left font-extrabold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-2 aria-pressed:outline-black">Décimal → hexadécimal</button>
<button type="button" data-type="c2" aria-pressed="false" class="border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] px-4 py-3 text-left font-extrabold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-2 aria-pressed:outline-black">Complément à 2</button>
<button type="button" data-type="chmod" aria-pressed="false" class="border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-left font-extrabold aria-pressed:outline aria-pressed:outline-4 aria-pressed:outline-offset-2 aria-pressed:outline-black">Droits chmod</button>
</div>
<div class="mt-4 border border-[#e3e5e8] rounded-2xl bg-black p-4 text-white">
<p class="font-extrabold">Mode examen</p>
<p class="mt-1 text-sm font-semibold">10 questions du type choisi, chrono, note sur 20.</p>
<button type="button" id="g-exam" class="mt-3 border-2 border-white bg-[#ec3013] px-3 py-1 font-extrabold">Lancer l’examen</button>
</div>
<p class="border border-[#dadce0] rounded-lg bg-white p-3 font-mono text-sm font-semibold">Série : <span id="g-serie">0</span> · Réussis : <span id="g-ok">0</span> / <span id="g-tot">0</span></p>
</aside>
<section class="lg:col-span-9" aria-live="polite">
<div id="g-barre" hidden class="mb-5 flex flex-wrap items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-[#ec3013] px-5 py-3 font-extrabold text-white"><span>MODE EXAMEN</span><span>Question <span id="g-qn">1</span> / 10</span><span class="ml-auto font-mono text-xl" id="g-chrono">00:00</span></div>
<form id="g-form" class="border border-[#e3e5e8] rounded-2xl bg-white p-7">
<p id="g-titre" class="font-mono text-sm font-semibold"></p>
<p id="g-enonce" class="mt-3 text-3xl font-extrabold leading-tight"></p>
<div id="g-champs" class="mt-6 grid gap-4 sm:grid-cols-3"></div>
<div class="mt-6 flex flex-wrap gap-4"><button type="submit" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white transition-transform hover:bg-[#ec3013]">Corriger</button><button type="button" id="g-new" class="inline-flex items-center gap-3 border border-[#e3e5e8] rounded-2xl bg-white px-5 py-3 font-extrabold hover:bg-[#fef7e0]">Nouvel exercice</button></div>
<div id="g-corr" hidden class="mt-6 border border-[#e3e5e8] rounded-2xl p-5"><p id="g-verdict" class="text-xl font-extrabold"></p><pre id="g-etapes" class="mt-3 whitespace-pre-wrap font-mono text-sm font-semibold"></pre></div>
</form>
<div id="g-fin" hidden class="mt-8 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-7"><p class="text-2xl font-extrabold">Examen terminé</p><p class="mt-2 font-mono text-7xl font-semibold"><span id="g-note">0</span> / 20</p><p id="g-temps" class="mt-2 text-lg font-bold"></p></div>
</section>
</div>
<script>
(function () {
var $ = function (id) { return document.getElementById(id); };
var type = 'reseau', cur = null, serie = 0, ok = 0, tot = 0, exam = null;
var r = function (a, b) { return a + Math.floor(Math.random() * (b - a + 1)); };
var ip = function (n) { return [n >>> 24, (n >>> 16) & 255, (n >>> 8) & 255, n & 255].join('.'); };
var b8 = function (n) { return (n & 255).toString(2).padStart(8, '0'); };
var G = {
reseau: function () {
var pref = [[10, r(0, 255)], [172, r(16, 31)], [192, 168]][r(0, 2)], a = ((pref[0] << 24) | (pref[1] << 16) | (r(0, 255) << 8) | r(1, 254)) >>> 0, c = r(20, 30);
var m = c === 0 ? 0 : (0xFFFFFFFF << (32 - c)) >>> 0, net = (a & m) >>> 0, bc = (net | (~m >>> 0)) >>> 0, h = Math.pow(2, 32 - c) - 2;
return { titre: 'Sous-réseaux · IPv4', enonce: ip(a) + '/' + c, champs: [['Adresse réseau', ip(net)], ['Diffusion', ip(bc)], ['Nombre d’hôtes', String(h)]],
etapes: 'Masque /' + c + ' = ' + ip(m) + '\nAdresse ET masque = ' + ip(net) + '\nBits d’hôte à 1 → diffusion ' + ip(bc) + '\nHôtes = 2^' + (32 - c) + ' − 2 = ' + h };
},
binaire: function () { var n = r(0, 255); return { titre: 'Conversion · décimal vers binaire (8 bits)', enonce: String(n), champs: [['En binaire', b8(n), function (v) { return /^[01]{1,8}$/.test(v) && parseInt(v, 2) === n; }]], etapes: [128, 64, 32, 16, 8, 4, 2, 1].map(function (p) { return p + ' → ' + ((n & p) ? '1' : '0'); }).join(' ') + '\n' + n + ' = ' + b8(n) }; },
hexa: function () { var n = r(0, 255), hx = n.toString(16).toUpperCase().padStart(2, '0'); return { titre: 'Conversion · décimal vers hexadécimal', enonce: String(n), champs: [['En hexadécimal', hx, function (v) { return parseInt(v.replace(/^0x/i, ''), 16) === n && /^(0x)?[0-9a-f]{1,2}$/i.test(v); }]], etapes: n + ' = ' + Math.floor(n / 16) + ' × 16 + ' + (n % 16) + '\n' + Math.floor(n / 16) + ' → ' + (Math.floor(n / 16)).toString(16).toUpperCase() + ', ' + (n % 16) + ' → ' + (n % 16).toString(16).toUpperCase() + '\nRésultat : ' + hx }; },
c2: function () { var n = r(-128, -1); return { titre: 'Complément à 2 · sur 8 bits', enonce: String(n), champs: [['Sur 8 bits', b8(n)]], etapes: '|' + n + '| = ' + (-n) + ' = ' + b8(-n) + '\nOn inverse les bits : ' + b8(~(-n)) + '\nOn ajoute 1 : ' + b8(n) }; },
chmod: function () {
var d = [r(4, 7), r(0, 7), r(0, 7)], s = function (x) { return (x & 4 ? 'r' : '-') + (x & 2 ? 'w' : '-') + (x & 1 ? 'x' : '-'); }, sym = d.map(s).join(''), oct = d.join('');
return Math.random() < .5
? { titre: 'Droits Linux · octal vers symbolique', enonce: 'chmod ' + oct, champs: [['Droits (ex. rwxr-x---)', sym]], etapes: d.map(function (x, i) { return ['propriétaire', 'groupe', 'autres'][i] + ' : ' + x + ' = ' + s(x); }).join('\n') + '\nr = 4, w = 2, x = 1' }
: { titre: 'Droits Linux · symbolique vers octal', enonce: sym, champs: [['En octal (ex. 750)', oct]], etapes: d.map(function (x, i) { return s(x) + ' = ' + x; }).join('\n') + '\nr = 4, w = 2, x = 1' };
}
};
function tirer() {
cur = G[type]();
$('g-titre').textContent = cur.titre; $('g-enonce').textContent = cur.enonce; $('g-corr').hidden = true;
$('g-champs').innerHTML = cur.champs.map(function (c, i) { return '<label class="grid gap-2 font-extrabold">' + c[0] + '<input data-i="' + i + '" autocomplete="off" class="w-full border border-[#e3e5e8] rounded-2xl bg-white px-4 py-3 text-lg font-semibold text-black placeholder:text-[#444141] focus:bg-[#f8f9fa] focus:outline-none font-mono"></label>'; }).join('');
var f = $('g-champs').querySelector('input'); if (f) f.focus();
if (exam) $('g-qn').textContent = exam.n + 1;
}
$('g-form').addEventListener('submit', function (e) {
e.preventDefault();
if (!$('g-corr').hidden) { if (exam) suivante(); return; }
var bons = 0;
cur.champs.forEach(function (c, i) {
var inp = $('g-champs').querySelector('[data-i="' + i + '"]'), v = inp.value.trim().replace(/\s/g, ''), juste = c[2] ? c[2](v) : v.toLowerCase() === c[1].toLowerCase();
if (juste) bons++; inp.classList.toggle('bg-[#e6f4ea]', juste); inp.classList.toggle('bg-[#FFD9E8]', !juste);
});
var tout = bons === cur.champs.length; tot++; if (tout) { ok++; serie++; } else serie = 0;
if (exam) exam.pts += bons / cur.champs.length;
$('g-serie').textContent = serie; $('g-ok').textContent = ok; $('g-tot').textContent = tot;
var cr = $('g-corr'); cr.hidden = false; cr.className = 'mt-6 border border-[#e3e5e8] rounded-2xl p-5 ' + (tout ? 'bg-[#e6f4ea]' : 'bg-[#FFD9E8]');
$('g-verdict').textContent = (tout ? 'Juste !' : 'Pas tout à fait.') + ' Réponse : ' + cur.champs.map(function (c) { return c[1]; }).join(' · ');
$('g-etapes').textContent = cur.etapes;
if (exam) $('g-new').textContent = exam.n === 9 ? 'Voir ma note' : 'Question suivante';
});
function suivante() { exam.n++; if (exam.n >= 10) return finir(); tirer(); }
function finir() {
clearInterval(exam.t); $('g-form').hidden = true; $('g-fin').hidden = false;
$('g-note').textContent = (Math.round(exam.pts * 2 * 10) / 10).toString().replace('.', ',');
$('g-temps').textContent = 'Temps : ' + $('g-chrono').textContent; exam = null; $('g-new').textContent = 'Nouvel exercice';
}
$('g-new').addEventListener('click', function () { if (exam) { if ($('g-corr').hidden) return; suivante(); } else tirer(); });
document.querySelectorAll('[data-type]').forEach(function (b) { b.addEventListener('click', function () { if (exam) return; type = b.dataset.type; document.querySelectorAll('[data-type]').forEach(function (x) { x.setAttribute('aria-pressed', x === b); }); tirer(); }); });
$('g-exam').addEventListener('click', function () {
var d = Date.now(); exam = { n: 0, pts: 0, t: setInterval(function () { var s = Math.floor((Date.now() - d) / 1000); $('g-chrono').textContent = String(Math.floor(s / 60)).padStart(2, '0') + ':' + String(s % 60).padStart(2, '0'); }, 1000) };
$('g-barre').hidden = false; $('g-fin').hidden = true; $('g-form').hidden = false; tirer();
});
tirer();
})();
</script>
@endsection

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,83 @@
@extends('layouts.vitrine')
@section('titre', 'Lab d’essai · Premiers pas dans le shell')
@push('head')
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.css">
<script defer src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.min.js"></script>
<script defer src="{{ asset('js/paillasse-terminal.js') }}"></script>
@endpush
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-[#fef7e0]">
<div class="mx-auto flex max-w-7xl flex-wrap items-center gap-4 px-5 py-4 lg:px-10">
<a href="{{ route('labs.index') }}" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#0b57d0] hover:text-white">← Labs</a>
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="flex-1 text-2xl font-extrabold tracking-tight">Premiers pas dans le shell</h1></div>
<span class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-mono text-sm font-semibold">Lab d’essai</span>
</div>
</section>
<section class="mx-auto grid max-w-7xl gap-8 px-5 py-10 lg:grid-cols-12 lg:px-10" aria-label="Espace de lab">
<article class="border border-[#e3e5e8] rounded-2xl bg-white p-6 lg:col-span-3" aria-labelledby="t-consignes">
<h2 id="t-consignes" class="text-2xl font-extrabold">Consignes</h2>
<ol id="consignes" class="mt-5 space-y-2 font-medium">
<li class="flex gap-3 p-2"><span class="font-mono font-semibold">1</span><span>Affiche le dossier courant avec <code class="bg-[#fef7e0] px-1 font-mono">pwd</code>.</span></li>
<li class="flex gap-3 p-2"><span class="font-mono font-semibold">2</span><span>Liste son contenu avec <code class="bg-[#fef7e0] px-1 font-mono">ls -la</code>.</span></li>
<li class="flex gap-3 p-2"><span class="font-mono font-semibold">3</span><span>Crée un dossier <code class="bg-[#fef7e0] px-1 font-mono">projets</code> et entre dedans.</span></li>
<li class="flex gap-3 p-2"><span class="font-mono font-semibold">4</span><span>Crée un fichier <code class="bg-[#fef7e0] px-1 font-mono">notes.txt</code>.</span></li>
<li class="flex gap-3 p-2"><span class="font-mono font-semibold">5</span><span>Écris ton prénom dedans avec <code class="bg-[#fef7e0] px-1 font-mono">echo</code>.</span></li>
</ol>
</article>
<div class="border border-[#e3e5e8] rounded-2xl bg-[#13233A] font-mono text-white lg:col-span-6">
<div class="flex items-center gap-2 border-b border-[#e3e5e8] bg-[#0d192b] px-4 py-2">
<span class="h-3 w-3 bg-[#ec3013]"></span><span class="h-3 w-3 bg-[#fef7e0]"></span><span class="h-3 w-3 bg-[#e6f4ea]"></span>
<span class="ml-2 text-sm">debian-lab · console 1 · xterm.js</span>
</div>
<div id="xterm-lab" class="h-[440px] bg-[#13233A] p-3"></div>
</div>
<aside class="flex flex-col gap-6 lg:col-span-3" aria-label="Vérification">
<div class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-5">
<h2 class="text-xl font-extrabold">Vérification</h2>
<p id="etape-texte" class="mt-2 font-extrabold" aria-live="polite">Tape ta première commande</p>
<div id="etape-barre" class="mt-3 grid grid-cols-5 gap-1"><span class="h-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-3 border border-[#dadce0] rounded-lg bg-white"></span><span class="h-3 border border-[#dadce0] rounded-lg bg-white"></span></div>
<p class="mt-4 text-sm font-semibold">Chaque étape se valide dès que la commande est juste.</p>
</div>
<details class="border border-[#e3e5e8] rounded-2xl bg-white p-5">
<summary class="cursor-pointer text-xl font-extrabold">Indice</summary>
<p class="mt-3 font-medium">La commande <code class="bg-[#fef7e0] px-1 font-mono">touch</code> crée un fichier vide.</p>
</details>
<button type="button" onclick="const on=this.getAttribute('aria-pressed')!=='true';this.setAttribute('aria-pressed',on);this.querySelector('span').textContent=on?'Main levée · le prof est prévenu':'Lever la main';" aria-pressed="false" class="border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] px-5 py-4 text-left text-lg font-extrabold transition-transform active:shadow-none aria-pressed:bg-[#fef7e0]"><span>Lever la main</span></button>
</aside>
</section>
<script>
document.addEventListener('DOMContentLoaded', function () {
var etapes = document.querySelectorAll('#consignes > li');
var barre = document.querySelectorAll('#etape-barre > span');
var texte = document.getElementById('etape-texte');
var fait = [false, false, false, false, false], vus = { pwd: false, ls: false };
function maj(sh) {
var h = sh.home, p = h + '/projets', n = p + '/notes.txt';
fait[0] = vus.pwd;
fait[1] = fait[0] && vus.ls;
fait[2] = fait[1] && sh.dirs.has(p) && sh.cwd === p;
fait[3] = fait[2] && sh.files.has(n);
fait[4] = fait[3] && (sh.files.get(n) || '').trim().length > 0;
var k = fait.indexOf(false); if (k === -1) k = 5;
etapes.forEach(function (li, i) {
li.className = 'flex gap-3 p-2 ' + (i < k ? 'line-through decoration-2' : i === k ? 'border border-[#dadce0] rounded-lg bg-[#e6f4ea]' : '');
});
barre.forEach(function (b, i) { b.className = 'h-3 border border-[#dadce0] rounded-lg ' + (i < k ? 'bg-black' : 'bg-white'); });
texte.textContent = k === 5 ? 'Lab terminé : 5 / 5 ✓' : k === 0 ? 'Tape ta première commande' : 'Étape ' + k + ' / 5 validée';
}
SyllabusTerminal.mount(document.getElementById('xterm-lab'), {
user: 'eleve', host: 'debian-lab', focus: true,
welcome: '\x1b[2mDebian GNU/Linux 13 · VM prête en 3,2 s\x1b[0m\nTape \x1b[93mhelp\x1b[0m pour voir les commandes.\n',
onCommand: function (line, sh) {
line.split(/&&|;/).forEach(function (c) { c = c.trim().split(/\s+/)[0]; if (c === 'pwd') vus.pwd = true; if (c === 'ls' && vus.pwd) vus.ls = true; });
maj(sh);
}
});
});
</script>
@endsection

View file

@ -0,0 +1,86 @@
@extends('layouts.vitrine')
@section('titre', 'Labs')
@section('contenu')
<section class="relative overflow-hidden border-b border-[#e3e5e8] bg-white">
<div aria-hidden="true" class="pointer-events-none absolute inset-0"><span class="flotte absolute right-[30%] bottom-10 h-9 w-9 rounded-full border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] [animation-delay:1.5s]"></span></div>
<div class="relative mx-auto max-w-7xl px-5 pb-20 pt-14 lg:px-10 lg:pt-20">
<p class="inline-block border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-3 py-1 text-sm font-bold">Catalogue</p>
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="mt-8 max-w-5xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl xl:text-7xl">Des labs qui se corrigent tout seuls.</h1></div>
<p class="mt-8 max-w-2xl text-xl font-medium leading-relaxed">Chaque lab est une vraie VM Debian, ou plusieurs reliées en réseau. L’élève suit les consignes, la vérification valide chaque étape.</p>
</div>
</section>
<section class="mx-auto max-w-7xl px-5 py-16 lg:px-10" aria-labelledby="titre-catalogue">
<div class="flex flex-wrap items-center gap-3">
<h2 id="titre-catalogue" class="mr-4 text-2xl font-extrabold">Filtrer</h2>
<button type="button" class="border border-[#dadce0] rounded-lg bg-black px-3 py-1 font-extrabold text-white">Tous</button>
<button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#fef7e0]">Linux</button>
<button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#e6f4ea]">Réseau</button>
<button type="button" class="border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#eef0fd]">Services</button>
</div>
<ul class="mt-14 grid gap-10 pb-12 sm:grid-cols-2 lg:grid-cols-3">
<li class="relative flex aspect-square flex-col justify-between border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-7">
<span class="absolute -right-4 -top-4 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Linux</span>
<span class="font-mono text-5xl font-semibold">01</span>
<div>
<p class="font-mono text-sm font-semibold">Lycée NSI</p>
<h3 class="mt-2 text-3xl font-extrabold leading-tight tracking-tight">Premiers pas dans le shell</h3>
<p class="mt-3 font-medium">Se déplacer, créer des dossiers, lire des fichiers.</p>
<a href="{{ route('labs.essai') }}" class="mt-5 inline-flex items-center gap-3 border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white hover:bg-[#ec3013]">Lancer le lab <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</li>
<li class="relative flex aspect-square flex-col justify-between border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-7">
<span class="absolute -right-4 -top-4 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Linux</span>
<span class="font-mono text-5xl font-semibold">02</span>
<div>
<p class="font-mono text-sm font-semibold">BTS SIO · SISR et SLAM</p>
<h3 class="mt-2 text-3xl font-extrabold leading-tight tracking-tight">Utilisateurs et droits</h3>
<p class="mt-3 font-medium">Créer des comptes, régler chmod et chown, tester les accès.</p>
<a href="{{ route('labs.essai') }}" class="mt-5 inline-flex items-center gap-3 border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white hover:bg-[#ec3013]">Lancer le lab <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</li>
<li class="relative flex aspect-square flex-col justify-between border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] p-7">
<span class="absolute -right-4 -top-4 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Réseau</span>
<span class="font-mono text-5xl font-semibold">03</span>
<div>
<p class="font-mono text-sm font-semibold">BTS CIEL</p>
<h3 class="mt-2 text-3xl font-extrabold leading-tight tracking-tight">Adressage IPv4</h3>
<p class="mt-3 font-medium">Configurer deux VM pour qu’elles se voient, puis diagnostiquer.</p>
<a href="{{ route('labs.essai') }}" class="mt-5 inline-flex items-center gap-3 border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white hover:bg-[#ec3013]">Lancer le lab <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</li>
<li class="relative flex aspect-square flex-col justify-between border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] p-7">
<span class="absolute -right-4 -top-4 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Réseau</span>
<span class="font-mono text-5xl font-semibold">04</span>
<div>
<p class="font-mono text-sm font-semibold">BUT · Licence pro</p>
<h3 class="mt-2 text-3xl font-extrabold leading-tight tracking-tight">Routage statique avec Kathará</h3>
<p class="mt-3 font-medium">Trois routeurs en conteneurs, une topologie à faire communiquer.</p>
<a href="{{ route('labs.essai') }}" class="mt-5 inline-flex items-center gap-3 border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white hover:bg-[#ec3013]">Lancer le lab <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</li>
<li class="relative flex aspect-square flex-col justify-between border border-[#e3e5e8] rounded-2xl bg-white p-7">
<span class="absolute -right-4 -top-4 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Services</span>
<span class="font-mono text-5xl font-semibold">05</span>
<div>
<p class="font-mono text-sm font-semibold">BTS SIO · SISR et SLAM</p>
<h3 class="mt-2 text-3xl font-extrabold leading-tight tracking-tight">Serveur web Apache</h3>
<p class="mt-3 font-medium">Installer, publier une page, lire les journaux.</p>
<a href="{{ route('labs.essai') }}" class="mt-5 inline-flex items-center gap-3 border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white hover:bg-[#ec3013]">Lancer le lab <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</li>
<li class="relative flex aspect-square flex-col justify-between border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-7">
<span class="absolute -right-4 -top-4 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Services</span>
<span class="font-mono text-5xl font-semibold">06</span>
<div>
<p class="font-mono text-sm font-semibold">Master · École d’ingé</p>
<h3 class="mt-2 text-3xl font-extrabold leading-tight tracking-tight">Annuaire Samba AD</h3>
<p class="mt-3 font-medium">Monter un contrôleur de domaine et joindre un client.</p>
<a href="{{ route('labs.essai') }}" class="mt-5 inline-flex items-center gap-3 border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white hover:bg-[#ec3013]">Lancer le lab <span class="font-mono" aria-hidden="true">→</span></a>
</div>
</li>
</ul>
</section>
@endsection

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,70 @@
@extends('layouts.vitrine')
@section('titre', 'Informations légales')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto max-w-7xl px-5 pb-14 pt-14 lg:px-10">
<p class="inline-block border border-[#dadce0] rounded-lg bg-[#eef0fd] px-3 py-1 text-sm font-bold">Informations légales</p>
<h1 class="mt-8 max-w-4xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Le cadre, en clair.</h1>
<p class="mt-6 font-mono text-sm font-semibold">Dernière mise à jour : 29 septembre 2026</p>
</div>
</section>
<div class="mx-auto grid max-w-7xl gap-10 px-5 py-14 lg:grid-cols-12 lg:px-10">
<nav class="lg:col-span-3" aria-label="Sommaire">
<ol class="sticky top-6 grid gap-2 font-extrabold">
<li><a href="#mentions" class="block border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2">Mentions légales</a></li><li><a href="#cgu" class="block border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-4 py-2">Conditions d’utilisation</a></li><li><a href="#confidentialite" class="block border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-4 py-2">Confidentialité et RGPD</a></li><li><a href="#cookies" class="block border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] px-4 py-2">Cookies</a></li><li><a href="#sous-traitance" class="block border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] px-4 py-2">Sous-traitance (art. 28)</a></li>
</ol>
</nav>
<div class="grid gap-12 lg:col-span-9">
<section id="mentions" class="scroll-mt-6 border border-[#e3e5e8] rounded-2xl bg-white p-7" aria-labelledby="t-mentions">
<h2 id="t-mentions" class="text-4xl font-extrabold tracking-tight">Mentions légales</h2>
<div class="mt-6 grid gap-4 text-lg font-medium leading-relaxed [&_h3]:mt-4 [&_h3]:text-xl [&_h3]:font-extrabold">
<p><strong>Éditeur :</strong> Syllabus, édité par Adam Belkacemi, <mark class="bg-[#fef7e0] px-1 font-bold">[à compléter]</mark> (forme juridique, capital, SIRET, adresse du siège).</p>
<p><strong>Directeur de la publication :</strong> Adam Belkacemi. <strong>Contact :</strong> adam@belkacemi.me.</p>
<p><strong>Hébergeur :</strong> Scaleway SAS, 8 rue de la Ville-l’Évêque, 75008 Paris. Les serveurs sont situés en France, à Paris.</p></div>
</section>
<section id="cgu" class="scroll-mt-6 border border-[#e3e5e8] rounded-2xl bg-white p-7" aria-labelledby="t-cgu">
<h2 id="t-cgu" class="text-4xl font-extrabold tracking-tight">Conditions générales d’utilisation</h2>
<div class="mt-6 grid gap-4 text-lg font-medium leading-relaxed [&_h3]:mt-4 [&_h3]:text-xl [&_h3]:font-extrabold">
<h3>1. Objet</h3><p>Syllabus met à disposition des cours, des labs Linux et réseau sur machines virtuelles, des QCM et des outils de suivi pour l’enseignement.</p>
<h3>2. Comptes</h3><p>Les enseignants créent un compte avec leur e-mail professionnel. Les élèves se connectent avec l’identifiant et le code remis par leur enseignant. Chacun est responsable de la confidentialité de ses accès.</p>
<h3>3. Accès gratuit</h3><p>L’accès enseignant est gratuit et sans carte bancaire. Syllabus peut faire évoluer les fonctionnalités et les limites d’usage, en prévenant les utilisateurs.</p>
<h3>4. Usage acceptable</h3><p>Les VM servent uniquement à l’apprentissage. Sont interdits : le minage, les attaques vers des tiers, le contournement des quotas ou du mode examen. Le trafic sortant des VM est bloqué par défaut et l’activité est journalisée.</p>
<h3>5. Mode examen</h3><p>Pendant une épreuve, les changements d’onglet, sorties de fenêtre et sorties de souris sont enregistrés et transmis à l’enseignant. L’élève en est informé avant de commencer.</p>
<h3>6. Contenus</h3><p>Les conditions de réutilisation des contenus pédagogiques seront précisées ultérieurement. Les travaux des élèves leur appartiennent.</p>
<h3>7. Disponibilité et responsabilité</h3><p>Syllabus fait ses meilleurs efforts pour assurer la disponibilité du service, sans garantie d’absence d’interruption. <mark class="bg-[#fef7e0] px-1 font-bold">[à compléter]</mark></p>
<h3>8. Droit applicable</h3><p>Les présentes conditions sont soumises au droit français.</p></div>
</section>
<section id="confidentialite" class="scroll-mt-6 border border-[#e3e5e8] rounded-2xl bg-white p-7" aria-labelledby="t-confidentialite">
<h2 id="t-confidentialite" class="text-4xl font-extrabold tracking-tight">Confidentialité et RGPD</h2>
<div class="mt-6 grid gap-4 text-lg font-medium leading-relaxed [&_h3]:mt-4 [&_h3]:text-xl [&_h3]:font-extrabold">
<p>Quand un établissement utilise Syllabus avec ses élèves, <strong>l’établissement est responsable du traitement</strong> et Syllabus agit comme <strong>sous-traitant</strong>. Pour les comptes enseignants créés directement, Syllabus est responsable du traitement.</p>
<h3>Données collectées</h3>
<ul class="grid gap-2"><li class="flex gap-3"><span aria-hidden="true">■</span><span>Élèves : nom, prénom, groupe. Aucun e-mail pour les mineurs.</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>Enseignants : nom, e-mail professionnel, établissement.</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>Activité pédagogique : étapes de TP, réponses aux QCM, temps passé, remarques des enseignants.</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>Mode examen : événements de sortie de copie, uniquement pendant l’épreuve.</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>Journaux techniques de sécurité.</span></li></ul>
<h3>Finalités et base légale</h3><p>Fournir le service d’enseignement demandé par l’établissement (mission d’intérêt public de l’établissement) ou par l’enseignant (exécution du contrat).</p>
<h3>Conservation</h3><p>Les données d’une classe sont supprimées automatiquement 90 jours après son archivage de fin d’année.</p>
<h3>Hébergement</h3><p>Toutes les données sont hébergées en France, chez Scaleway. Elles ne quittent pas l’Union européenne. Aucune donnée n’est vendue ni utilisée à des fins publicitaires.</p>
<h3>Vos droits</h3><p>Accès, rectification, effacement, limitation, opposition et portabilité : écrivez à adam@belkacemi.me ou à votre établissement. Vous pouvez aussi adresser une réclamation à la CNIL (cnil.fr).</p>
<p><strong>Délégué à la protection des données :</strong> <mark class="bg-[#fef7e0] px-1 font-bold">[à compléter]</mark></p></div>
</section>
<section id="cookies" class="scroll-mt-6 border border-[#e3e5e8] rounded-2xl bg-white p-7" aria-labelledby="t-cookies">
<h2 id="t-cookies" class="text-4xl font-extrabold tracking-tight">Cookies</h2>
<div class="mt-6 grid gap-4 text-lg font-medium leading-relaxed [&_h3]:mt-4 [&_h3]:text-xl [&_h3]:font-extrabold">
<p>Syllabus n’utilise que des cookies strictement nécessaires : le cookie de session qui vous garde connecté, et le jeton de sécurité des formulaires. Aucun cookie publicitaire, aucun traceur tiers. Ils ne demandent donc pas de consentement.</p></div>
</section>
<section id="sous-traitance" class="scroll-mt-6 border border-[#e3e5e8] rounded-2xl bg-white p-7" aria-labelledby="t-sous-traitance">
<h2 id="t-sous-traitance" class="text-4xl font-extrabold tracking-tight">Accord de sous-traitance (article 28 du RGPD)</h2>
<div class="mt-6 grid gap-4 text-lg font-medium leading-relaxed [&_h3]:mt-4 [&_h3]:text-xl [&_h3]:font-extrabold">
<p>Pour chaque établissement, un accord de sous-traitance précise :</p>
<ul class="grid gap-2"><li class="flex gap-3"><span aria-hidden="true">■</span><span>l’objet, la durée et la nature des traitements ;</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>les mesures de sécurité : chiffrement en transit, isolement des classes, sauvegardes chiffrées ;</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>la confidentialité des personnes autorisées ;</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>la liste des sous-traitants ultérieurs (hébergement : Scaleway SAS, France) ;</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>l’assistance pour répondre aux demandes de droits ;</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>la notification des violations de données ;</span></li><li class="flex gap-3"><span aria-hidden="true">■</span><span>la suppression ou la restitution des données en fin de contrat.</span></li></ul>
<p><a href="{{ route('etablissements') }}" class="font-extrabold underline underline-offset-4">Demander l’accord pour votre établissement</a></p></div>
</section>
</div>
</div>
@endsection

View file

@ -0,0 +1,29 @@
@extends('layouts.vitrine')
@section('titre', 'Ressources à la maison')
@section('contenu')
<section class="border-b border-[#e3e5e8] bg-white">
<div class="mx-auto max-w-7xl px-5 pb-12 pt-12 lg:px-10">
<p class="inline-block border border-[#dadce0] rounded-lg bg-[#e6f4ea] px-3 py-1 text-sm font-bold">Pour les élèves</p>
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="mt-6 max-w-5xl text-6xl font-extrabold leading-[1.05] tracking-tight sm:text-7xl">Envie d’aller plus loin à la maison&nbsp;?</h1></div>
<p class="mt-6 max-w-3xl text-xl font-medium leading-relaxed">Sur Syllabus, tu retrouves tes cours, tes QCM, l’IDE et le générateur de TD depuis chez toi, sur ton PC ou ton téléphone. Et si tu en veux encore, voici des ressources gratuites, sérieuses et en grande partie en français.</p>
<div class="mt-8 flex flex-wrap gap-4"><a href="{{ route('ide') }}" class="inline-flex items-center gap-4 border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-lg font-extrabold text-white hover:bg-[#ec3013]">Coder dans l’IDE →</a><a href="{{ route('generateur') }}" class="inline-flex items-center border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] px-6 py-4 text-lg font-extrabold">S’entraîner au générateur de TD</a><a href="{{ route('cours.index') }}" class="inline-flex items-center border border-[#e3e5e8] rounded-2xl bg-white px-6 py-4 text-lg font-extrabold hover:bg-[#fef7e0]">Relire les cours</a></div>
</div>
</section>
<section class="mx-auto max-w-7xl px-5 py-16 lg:px-10" aria-labelledby="t-ext">
<h2 id="t-ext" class="text-4xl font-extrabold tracking-tight">Ressources externes gratuites</h2>
<p class="mt-3 max-w-2xl text-lg font-semibold">Elles ne font pas partie de Syllabus. Certaines demandent de créer un compte : demande l’accord de tes parents si tu es mineur.</p>
<ul id="ext" class="mt-10 grid gap-8 sm:grid-cols-2 lg:grid-cols-3"></ul>
</section>
<script src="{{ asset('js/referentiel.js') }}"></script>
<script>
(function () {
var C = ["bg-[#fef7e0]","bg-[#e6f4ea]","bg-[#eef0fd]","bg-[#fce8e6]","bg-white"];
document.getElementById('ext').innerHTML = window.REFERENTIEL.plusLoin.map(function (r, i) {
return '<li class="flex flex-col border border-[#e3e5e8] rounded-2xl ' + C[i % C.length] + ' p-6 ' + (i % 3 === 1 ? '' : '') + '"><p class="font-mono text-xs font-semibold uppercase">' + r[0] + '</p><p class="mt-2 text-2xl font-extrabold">' + r[1] + '</p><p class="mt-2 flex-1 font-semibold">' + r[3] + '</p><a href="' + r[2] + '" target="_blank" rel="noopener" class="mt-4 self-start border border-[#dadce0] rounded-lg bg-white px-3 py-1 font-extrabold hover:bg-[#0b57d0] hover:text-white">Ouvrir ↗</a></li>';
}).join('');
})();
</script>
@endsection

View file

@ -0,0 +1,35 @@
@extends('layouts.vitrine')
@section('titre', 'Mes classes')
@section('contenu')
<div class="mx-auto max-w-5xl px-5 py-14 lg:px-10">
<h1 class="text-4xl font-extrabold tracking-tight">Mes classes</h1>
@if (session('session_precedente_fermee'))
<p class="mt-4 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-4 font-semibold">
Une session précédente sur ce compte a été fermée : une seule session active à la fois.
</p>
@endif
@if ($classes->isEmpty())
<p class="mt-6 font-semibold">Aucune classe pour l'instant.</p>
@else
<ul class="mt-8 grid gap-4">
@foreach ($classes as $classe)
<li>
<a href="{{ route('mes-classes.show', $classe) }}" class="flex flex-wrap items-center justify-between gap-3 border border-[#e3e5e8] rounded-2xl bg-white p-5 hover:bg-[#f8f9fa]">
<span>
<span class="block text-xl font-extrabold">{{ $classe->nom }}</span>
@if ($classe->formation)
<span class="block font-semibold">{{ $classe->formation }}</span>
@endif
</span>
<span class="font-mono text-sm font-semibold">{{ $classe->eleves_count }} élève(s)</span>
</a>
</li>
@endforeach
</ul>
@endif
</div>
@endsection

View file

@ -0,0 +1,113 @@
@extends('layouts.vitrine')
@section('titre', $classe->nom)
@section('contenu')
<div class="mx-auto max-w-5xl px-5 py-14 lg:px-10">
<div class="flex flex-wrap items-end justify-between gap-4">
<div>
<h1 class="text-4xl font-extrabold tracking-tight">{{ $classe->nom }}</h1>
@if ($classe->formation)
<p class="mt-1 text-lg font-semibold">{{ $classe->formation }}</p>
@endif
</div>
<p class="font-mono text-sm font-semibold">Code de classe : <span class="rounded-lg border border-[#dadce0] bg-white px-2 py-1">{{ $classe->code_classe }}</span></p>
</div>
@if (session('classe_creee'))
<p class="mt-4 border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-4 font-semibold">Classe créée. Ajoute maintenant tes élèves ci-dessous.</p>
@endif
@if (session('fiches'))
<section class="mt-10 border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-6 print:border-0 print:bg-white" aria-labelledby="t-fiches">
<div class="flex flex-wrap items-center justify-between gap-3 print:hidden">
<h2 id="t-fiches" class="text-2xl font-extrabold">
Fiches à imprimer
@if (session('nombre_importes'))
<span class="font-mono text-sm font-semibold">({{ session('nombre_importes') }} élève(s) importé(s))</span>
@endif
</h2>
<button type="button" onclick="window.print()" class="border border-[#dadce0] rounded-lg bg-black px-4 py-2 font-extrabold text-white">Imprimer</button>
</div>
<p class="mt-2 font-semibold print:hidden">Le code secret ne sera plus jamais affiché après cette page : imprime ou note-le maintenant.</p>
<div class="mt-6 grid gap-4 sm:grid-cols-2 print:grid-cols-1">
@foreach (session('fiches') as $fiche)
<div class="flex items-center gap-4 border border-[#dadce0] rounded-2xl bg-white p-5 print:break-inside-avoid">
<div class="shrink-0">{!! \App\Support\QrCode::svg(route('connexion.qr', $fiche['jeton_qr'])) !!}</div>
<div class="min-w-0">
<p class="text-lg font-extrabold">{{ $fiche['prenom'] }}@if($fiche['nom']) {{ $fiche['nom'] }}@endif</p>
<p class="mt-2 font-mono text-sm">Identifiant<br><span class="text-lg font-bold">{{ $fiche['identifiant'] }}</span></p>
<p class="mt-2 font-mono text-sm">Code secret<br><span class="text-lg font-bold">{{ $fiche['code_secret'] }}</span></p>
</div>
</div>
@endforeach
</div>
</section>
@endif
<div class="mt-10 grid gap-6 sm:grid-cols-2">
<section class="border border-[#e3e5e8] rounded-2xl bg-white p-6" aria-labelledby="t-ajout">
<h2 id="t-ajout" class="text-xl font-extrabold">Ajouter un élève</h2>
@error('prenom')<p class="mt-2 font-bold text-[#A63D2A]">{{ $message }}</p>@enderror
<form action="{{ route('mes-classes.eleves.store', $classe) }}" method="post" class="mt-4 grid gap-3">
@csrf
<label class="grid gap-1 font-bold">Prénom<input name="prenom" required class="w-full rounded-xl border border-[#c4c7c5] bg-white px-3 py-2 font-semibold"></label>
<label class="grid gap-1 font-bold">Nom <span class="font-medium">(facultatif, visible de toi seul)</span><input name="nom" class="w-full rounded-xl border border-[#c4c7c5] bg-white px-3 py-2 font-semibold"></label>
<button type="submit" class="mt-2 inline-flex h-11 items-center justify-center rounded-full bg-[#0b57d0] px-5 font-bold text-white">Ajouter</button>
</form>
</section>
<section class="border border-[#e3e5e8] rounded-2xl bg-white p-6" aria-labelledby="t-import">
<h2 id="t-import" class="text-xl font-extrabold">Importer une liste (CSV)</h2>
<p class="mt-2 font-semibold">Une ligne par élève : <code class="font-mono">prenom,nom</code> (le nom peut être vide).</p>
@error('fichier')<p class="mt-2 font-bold text-[#A63D2A]">{{ $message }}</p>@enderror
<form action="{{ route('mes-classes.eleves.importer', $classe) }}" method="post" enctype="multipart/form-data" class="mt-4 grid gap-3">
@csrf
<input type="file" name="fichier" accept=".csv,text/csv" required class="w-full rounded-xl border border-[#c4c7c5] bg-white px-3 py-2 font-semibold">
<button type="submit" class="mt-2 inline-flex h-11 items-center justify-center rounded-full bg-[#0b57d0] px-5 font-bold text-white">Importer</button>
</form>
</section>
</div>
<section class="mt-10 border border-[#e3e5e8] rounded-2xl bg-white" aria-labelledby="t-eleves">
<h2 id="t-eleves" class="p-6 pb-0 text-2xl font-extrabold">Élèves ({{ $classe->eleves->count() }})</h2>
@if ($classe->eleves->isEmpty())
<p class="p-6 font-semibold">Aucun élève pour l'instant.</p>
@else
<div class="overflow-x-auto">
<table class="mt-4 w-full min-w-[480px] text-left">
<thead class="bg-[#0b57d0] text-white"><tr><th class="px-4 py-2">Élève</th><th class="px-4 py-2 font-mono text-xs">Identifiant</th><th class="px-4 py-2">Dernière connexion</th><th class="px-4 py-2"></th></tr></thead>
<tbody class="divide-y divide-[#e3e5e8]">
@foreach ($classe->eleves as $eleve)
<tr>
<td class="px-4 py-3 font-extrabold">{{ $eleve->nomAffiche() }}</td>
<td class="px-4 py-3 font-mono text-sm">{{ $eleve->identifiant }}</td>
<td class="px-4 py-3 font-semibold">{{ $eleve->derniere_connexion_a?->diffForHumans() ?? 'jamais' }}</td>
<td class="px-4 py-3">
<form action="{{ route('mes-classes.eleves.regenererCode', [$classe, $eleve]) }}" method="post" onsubmit="return confirm('Régénérer le code de {{ $eleve->prenom }} ? L’ancien code ne fonctionnera plus.');">
@csrf
<button type="submit" class="font-bold underline underline-offset-4">Régénérer le code</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</section>
<section class="mt-10 border border-[#e3e5e8] rounded-2xl bg-white p-6" aria-labelledby="t-seance">
<h2 id="t-seance" class="text-2xl font-extrabold">Lancer une séance</h2>
<p class="mt-2 font-semibold">Les élèves qui rejoignent patientent dans la salle d'attente jusqu'à ce que tu les admettes.</p>
<form action="{{ route('mes-classes.seances.store', $classe) }}" method="post" class="mt-4 flex flex-wrap items-end gap-3">
@csrf
<label class="grid gap-1 font-bold">Lab<select name="lab_id" required class="rounded-xl border border-[#c4c7c5] bg-white px-3 py-2 font-semibold">
@foreach (\App\Models\Lab::orderBy('titre')->get() as $lab)
<option value="{{ $lab->id }}">{{ $lab->titre }}</option>
@endforeach
</select></label>
<button type="submit" class="inline-flex h-11 items-center justify-center rounded-full bg-black px-5 font-bold text-white">Ouvrir la salle d'attente</button>
</form>
</section>
</div>
@endsection

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Quiz flash · Syllabus</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@500;700;800;900&family=IBM+Plex+Mono:wght@400;600&display=swap" rel="stylesheet">
@vite(['resources/css/app.css', 'resources/js/app.js'])
<style>
.etoile { clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); }
.zigzag { background: linear-gradient(135deg, transparent 50%, #000 50% 62%, transparent 62%) 0 0 / 16px 16px, linear-gradient(45deg, transparent 50%, #000 50% 62%, transparent 62%) 0 0 / 16px 16px; }
@keyframes flotte { 0%,100% { transform: translateY(0) rotate(var(--r, 0deg)); } 50% { transform: translateY(-10px) rotate(var(--r, 0deg)); } }
.flotte { animation: flotte 6s ease-in-out infinite; }
@keyframes clignote { 50% { opacity: 0; } }
.curseur { animation: clignote 1s steps(1) infinite; }
@media (prefers-reduced-motion: reduce) { .flotte, .curseur { animation: none; } }
</style>
<link rel="stylesheet" href="{{ asset('css/syllabus-theme.css') }}">
</head>
<body class="min-h-screen bg-[#eef0fd] font-display text-black antialiased">
<main class="mx-auto flex min-h-screen max-w-md flex-col gap-6 px-5 py-8">
<p class="self-start border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-extrabold">Vue élève · téléphone ou PC</p>
<section id="e-login" class="border border-[#e3e5e8] rounded-2xl bg-white p-6">
<div class="min-w-0 flex-1"><p data-public="E" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#0b5e3c]">Pour les élèves</p>
<h1 class="text-4xl font-extrabold leading-none tracking-tight">Quiz flash</h1></div>
<form id="f-login" class="mt-6 grid gap-4">
<label class="grid gap-2 font-extrabold">Code du quiz<input required value="K7Q4" maxlength="4" class="w-full border border-[#e3e5e8] rounded-2xl px-4 py-3 font-mono text-3xl font-semibold uppercase tracking-widest focus:bg-[#f8f9fa] focus:outline-none"></label>
<label class="grid gap-2 font-extrabold">Identifiant<input required value="lea.m.sio1-a" autocomplete="username" class="w-full border border-[#e3e5e8] rounded-2xl px-4 py-3 font-mono text-lg font-semibold focus:bg-[#f8f9fa] focus:outline-none"></label>
<label class="grid gap-2 font-extrabold">Code secret<input required type="password" value="••••••" autocomplete="current-password" class="w-full border border-[#e3e5e8] rounded-2xl px-4 py-3 font-mono text-lg font-semibold focus:bg-[#f8f9fa] focus:outline-none"></label>
<button type="submit" class="min-h-[56px] border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-left text-xl font-extrabold text-white">Rejoindre →</button>
</form>
</section>
<section id="e-attente" hidden class="border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] p-6 text-center">
<p class="text-3xl font-extrabold">Tu es connectée, Léa&nbsp;!</p>
<p class="mt-3 text-lg font-bold">Regarde l’écran. La question arrive…</p>
<button type="button" id="e-go" class="mt-6 border border-[#dadce0] rounded-lg bg-white px-3 py-1 text-sm font-bold underline">Aperçu : afficher la question</button>
</section>
<section id="e-question" hidden>
<p class="font-mono font-semibold">Question 3 / 5 · la question est affichée au tableau</p>
<div class="mt-4 grid grid-cols-2 gap-4">
<button type="button" data-choix="0" class="grid aspect-square place-items-center border border-[#e3e5e8] rounded-2xl bg-[#fce8e6] font-mono text-6xl font-semibold active:shadow-none">A</button>
<button type="button" data-choix="1" class="grid aspect-square place-items-center border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] font-mono text-6xl font-semibold active:shadow-none">B</button>
<button type="button" data-choix="2" class="grid aspect-square place-items-center border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] font-mono text-6xl font-semibold active:shadow-none">C</button>
<button type="button" data-choix="3" class="grid aspect-square place-items-center border border-[#e3e5e8] rounded-2xl bg-[#eef0fd] font-mono text-6xl font-semibold active:shadow-none">D</button>
</div>
</section>
<section id="e-envoye" hidden class="border border-[#e3e5e8] rounded-2xl bg-white p-6">
<p class="text-3xl font-extrabold">Réponse <span id="e-lettre"></span> envoyée ✓</p>
<p class="mt-2 text-lg font-bold">Attends la correction au tableau.</p>
</section>
</main>
<script>
(function () {
var $ = function (id) { return document.getElementById(id); };
$('f-login').addEventListener('submit', function (e) { e.preventDefault(); $('e-login').hidden = true; $('e-attente').hidden = false; });
$('e-go').addEventListener('click', function () { $('e-attente').hidden = true; $('e-question').hidden = false; });
document.querySelectorAll('[data-choix]').forEach(function (b) { b.addEventListener('click', function () { $('e-lettre').textContent = b.textContent.trim(); $('e-question').hidden = true; $('e-envoye').hidden = false; }); });
})();
</script>
</body>
</html>

View file

@ -0,0 +1,162 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Quiz flash · projection · Syllabus</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@500;700;800;900&family=IBM+Plex+Mono:wght@400;600&display=swap" rel="stylesheet">
@vite(['resources/css/app.css', 'resources/js/app.js'])
<style>
.etoile { clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); }
.zigzag { background: linear-gradient(135deg, transparent 50%, #000 50% 62%, transparent 62%) 0 0 / 16px 16px, linear-gradient(45deg, transparent 50%, #000 50% 62%, transparent 62%) 0 0 / 16px 16px; }
@keyframes flotte { 0%,100% { transform: translateY(0) rotate(var(--r, 0deg)); } 50% { transform: translateY(-10px) rotate(var(--r, 0deg)); } }
.flotte { animation: flotte 6s ease-in-out infinite; }
@keyframes clignote { 50% { opacity: 0; } }
.curseur { animation: clignote 1s steps(1) infinite; }
@media (prefers-reduced-motion: reduce) { .flotte, .curseur { animation: none; } }
</style>
<link rel="stylesheet" href="{{ asset('css/syllabus-theme.css') }}">
</head>
<body class="min-h-screen bg-white font-display text-black antialiased">
<div id="scene" class="flex min-h-screen flex-col">
<header class="flex flex-wrap items-center gap-4 border-b-4 border-black bg-black px-6 py-3 text-white">
<span class="border-2 border-white bg-[#FFD23F] px-3 py-1 font-extrabold text-black">QUIZ FLASH</span>
<p class="flex-1 font-bold">BTS SIO 1 · Groupe A · ls, chmod, grep, ip, ping</p>
<p class="font-mono"><span id="p-count">0</span> / 24 connectés</p>
<button type="button" id="plein" class="border-2 border-white px-3 py-1 font-extrabold hover:bg-white hover:text-black">Plein écran</button>
</header>
<section id="s-attente" class="grid flex-1 gap-8 p-8 lg:grid-cols-12">
<div class="flex flex-col justify-center lg:col-span-7">
<p class="text-3xl font-extrabold">Sur ton téléphone ou ton PC, va sur</p>
<p class="mt-4 inline-block self-start border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-5 py-3 font-mono text-5xl font-semibold">syllabus.fr/quiz</p>
<p class="mt-10 text-3xl font-extrabold">et entre le code</p>
<p class="mt-4 inline-block self-start border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] px-6 py-4 font-mono text-8xl font-semibold tracking-widest">K7Q4</p>
<p class="mt-10 text-xl font-bold">Connecte-toi avec ton identifiant Syllabus.</p>
</div>
<div class="flex flex-col border border-[#e3e5e8] rounded-2xl bg-white lg:col-span-5">
<div class="flex items-center justify-between border-b border-[#e3e5e8] bg-[#eef0fd] px-5 py-3"><p class="text-xl font-extrabold">Présences</p><p class="font-mono font-semibold"><span id="p-count2">0</span> / 24</p></div>
<ul id="presences" class="grid flex-1 content-start grid-cols-2 gap-2 overflow-y-auto p-4 text-sm font-bold sm:grid-cols-3">
<li data-eleve="Léa M." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Léa M.</li>
<li data-eleve="Yanis B." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Yanis B.</li>
<li data-eleve="Nora Kaci" class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Nora Kaci</li>
<li data-eleve="Tom R." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Tom R.</li>
<li data-eleve="Inès D." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Inès D.</li>
<li data-eleve="Sami L." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Sami L.</li>
<li data-eleve="Chloé P." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Chloé P.</li>
<li data-eleve="Adam F." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Adam F.</li>
<li data-eleve="Maël G." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Maël G.</li>
<li data-eleve="Jade T." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Jade T.</li>
<li data-eleve="Hugo M." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Hugo M.</li>
<li data-eleve="Lina G." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Lina G.</li>
<li data-eleve="Rayan F." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Rayan F.</li>
<li data-eleve="Emma B." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Emma B.</li>
<li data-eleve="Noah H." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Noah H.</li>
<li data-eleve="Sarah R." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Sarah R.</li>
<li data-eleve="Ilyes M." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Ilyes M.</li>
<li data-eleve="Manon L." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Manon L.</li>
<li data-eleve="Lucas M." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Lucas M.</li>
<li data-eleve="Zoé D." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Zoé D.</li>
<li data-eleve="Enzo L." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Enzo L.</li>
<li data-eleve="Camille B." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Camille B.</li>
<li data-eleve="Nathan F." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Nathan F.</li>
<li data-eleve="Anaïs L." class="flex items-center gap-2 border border-[#dadce0] rounded-lg bg-white px-2 py-1 opacity-40"><span data-pastille class="h-3 w-3 shrink-0 border border-[#dadce0] rounded-lg bg-white"></span>Anaïs L.</li>
</ul>
<div class="border-t border-[#e3e5e8] p-4">
<p id="manquants" class="font-bold">En attente des connexions…</p>
<button type="button" id="demarrer" class="mt-4 w-full border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-left text-xl font-extrabold text-white hover:bg-[#ec3013]">Démarrer le quiz →</button>
</div>
</div>
</section>
<section id="s-question" hidden class="flex flex-1 flex-col p-8">
<div class="flex flex-wrap items-center gap-4">
<p class="border border-[#e3e5e8] rounded-2xl bg-white px-4 py-2 font-mono text-xl font-semibold">Question <span id="q-num">1</span> / 5</p>
<div class="h-6 flex-1 border border-[#e3e5e8] rounded-2xl bg-white"><div id="q-timer" class="h-full bg-[#ec3013]" style="width:100%"></div></div>
<p class="font-mono text-3xl font-semibold"><span id="q-sec">20</span> s</p>
</div>
<div class="min-w-0 flex-1"><p data-public="P" class="mb-2 inline-flex items-center gap-2 rounded-full border border-[#b8c1cf] bg-white px-3 py-1 text-sm font-bold text-[#1d3fa8]">Pour les profs</p>
<h1 id="q-texte" class="mt-10 max-w-5xl text-5xl font-extrabold leading-tight tracking-tight lg:text-7xl"></h1></div>
<ol id="q-reps" class="mt-10 grid flex-1 content-start gap-5 md:grid-cols-2"></ol>
<div class="mt-8 flex flex-wrap items-center gap-5">
<p class="text-2xl font-extrabold"><span id="q-rep">0</span> / <span id="q-pres">0</span> ont répondu</p>
<p id="q-expl" hidden class="flex-1 border border-[#e3e5e8] rounded-2xl bg-[#e6f4ea] px-5 py-3 text-xl font-bold"></p>
<button type="button" id="suivant" class="ml-auto border border-[#e3e5e8] rounded-2xl bg-black px-6 py-4 text-xl font-extrabold text-white">Afficher la réponse →</button>
</div>
</section>
<section id="s-fin" hidden class="grid flex-1 content-center gap-8 p-8 lg:grid-cols-3">
<div class="border border-[#e3e5e8] rounded-2xl bg-[#fef7e0] p-8 lg:col-span-2">
<p class="text-2xl font-extrabold">Quiz terminé&nbsp;!</p>
<p class="mt-4 font-mono text-8xl font-semibold"><span id="f-score">0</span> %</p>
<p class="mt-2 text-2xl font-bold">de bonnes réponses pour la classe</p>
<p id="f-rate" class="mt-6 border-t border-[#e3e5e8] pt-4 text-xl font-bold"></p>
</div>
<div class="border border-[#e3e5e8] rounded-2xl bg-white p-6">
<p class="text-xl font-extrabold">Absents au quiz</p>
<ul class="mt-3 grid gap-2 font-bold"><li class="border border-[#dadce0] rounded-lg bg-[#FFE4DF] px-3 py-1">Inès D.</li><li class="border border-[#dadce0] rounded-lg bg-[#FFE4DF] px-3 py-1">Hugo M.</li><li class="border border-[#dadce0] rounded-lg bg-[#FFE4DF] px-3 py-1">Jade T.</li></ul>
<p class="mt-4 font-semibold">Résultats enregistrés dans le suivi de la classe.</p>
<a href="{{ route('banque') }}" class="mt-5 inline-block border border-[#e3e5e8] rounded-2xl bg-black px-4 py-2 font-extrabold text-white">Retour à la banque</a>
</div>
</section>
</div>
<script>
(function () {
var Q = [["Que fait ls -a en plus de ls ?",["Affiche les fichiers cachés","Affiche les droits","Affiche la taille en Ko","N’affiche que les dossiers"],0,"L’option -a (all) affiche aussi les fichiers qui commencent par un point, comme .bashrc."],["chmod 750 script.sh donne au groupe…",["Lecture et exécution","Lecture seule","Tous les droits","Aucun droit"],0,"7 = rwx pour le propriétaire, 5 = r-x pour le groupe, 0 = rien pour les autres."],["Quelle commande cherche « erreur » dans app.log ?",["find erreur app.log","grep erreur app.log","cat -s erreur app.log","ls erreur app.log"],1,"grep affiche les lignes d’un fichier qui contiennent un motif."],["À quoi sert ip a ?",["Pinger une machine","Ajouter une route","Afficher les adresses des interfaces","Redémarrer le réseau"],2,"ip a (ip address) liste les interfaces réseau et leurs adresses IP."],["ping -c 4 8.8.8.8 envoie…",["Pendant 4 secondes","4 paquets puis s’arrête","À 4 machines","4 fois plus vite"],1,"L’option -c (count) fixe le nombre de paquets envoyés."]], COL = ["bg-[#fce8e6]","bg-[#e6f4ea]","bg-[#fef7e0]","bg-[#eef0fd]"], ABS = ["Inès D.","Hugo M.","Jade T."], L = 'ABCD';
var eleves = Array.prototype.slice.call(document.querySelectorAll('[data-eleve]')), connectes = 0, i = -1, phase = 'q', tic, bons = 0, total = 0, rate = [];
var $ = function (id) { return document.getElementById(id); };
var file = eleves.filter(function (li) { return ABS.indexOf(li.dataset.eleve) === -1; });
file.sort(function () { return Math.random() - .5; });
var joins = setInterval(function () {
var li = file.shift(); if (!li) { clearInterval(joins); return; }
li.classList.remove('opacity-40'); li.classList.add('bg-[#e6f4ea]'); li.querySelector('[data-pastille]').classList.replace('bg-white', 'bg-black');
connectes++; $('p-count').textContent = $('p-count2').textContent = connectes;
var m = eleves.filter(function (e) { return e.classList.contains('opacity-40'); }).map(function (e) { return e.dataset.eleve; });
$('manquants').innerHTML = m.length ? '<span class="bg-[#ec3013] px-1 text-white">Manquants : ' + m.length + '</span> ' + m.join(', ') : 'Tout le monde est là ✓';
$('demarrer').textContent = 'Démarrer le quiz (' + connectes + ' / ' + eleves.length + ') →';
}, 350);
function question() {
i++; phase = 'q';
if (i >= Q.length) return fin();
var q = Q[i], t = 20, rep = 0;
$('q-num').textContent = i + 1; $('q-texte').textContent = q[0]; $('q-pres').textContent = connectes; $('q-rep').textContent = 0;
$('q-expl').hidden = true; $('suivant').textContent = 'Afficher la réponse →';
$('q-reps').innerHTML = q[1].map(function (r, k) {
return '<li data-r class="flex items-center gap-5 border border-[#e3e5e8] rounded-2xl ' + COL[k] + ' p-6 text-3xl font-extrabold"><span class="grid h-14 w-14 shrink-0 place-items-center border border-[#e3e5e8] rounded-2xl bg-white font-mono">' + L[k] + '</span><span class="flex-1">' + r + '</span><span data-pc class="font-mono text-2xl" hidden></span></li>';
}).join('');
clearInterval(tic);
tic = setInterval(function () {
t--; $('q-sec').textContent = Math.max(0, t); $('q-timer').style.width = Math.max(0, t / 20 * 100) + '%';
if (rep < connectes && Math.random() < .55) { rep = Math.min(connectes, rep + 1 + Math.floor(Math.random() * 3)); $('q-rep').textContent = rep; }
if (t <= 0) reponse();
}, 1000);
}
function reponse() {
clearInterval(tic); phase = 'r';
var q = Q[i], ok = q[2], n = Number($('q-rep').textContent) || connectes, part = [0, 0, 0, 0];
var pBon = .45 + Math.random() * .45; part[ok] = Math.round(n * pBon);
var reste = n - part[ok]; [0, 1, 2, 3].filter(function (k) { return k !== ok; }).forEach(function (k, j, arr) { var v = j === arr.length - 1 ? reste : Math.floor(Math.random() * (reste + 1)); part[k] = v; reste -= v; });
bons += part[ok]; total += n; rate.push([i + 1, Math.round(pBon * 100)]);
document.querySelectorAll('#q-reps [data-r]').forEach(function (li, k) {
var pc = li.querySelector('[data-pc]'); pc.hidden = false; pc.textContent = part[k] + ' élève' + (part[k] > 1 ? 's' : '');
if (k !== ok) li.classList.add('opacity-40'); else li.classList.add('outline', 'outline-8', 'outline-black');
});
$('q-expl').hidden = false; $('q-expl').textContent = '✓ ' + q[3];
$('suivant').textContent = i === Q.length - 1 ? 'Voir le bilan →' : 'Question suivante →';
}
function fin() {
$('s-question').hidden = true; $('s-fin').hidden = false;
$('f-score').textContent = Math.round(bons / Math.max(1, total) * 100);
var pire = rate.slice().sort(function (a, b) { return a[1] - b[1]; })[0];
$('f-rate').textContent = 'À revoir en cours : question ' + pire[0] + ' (' + pire[1] + ' % de réussite).';
}
$('demarrer').addEventListener('click', function () { clearInterval(joins); $('s-attente').hidden = true; $('s-question').hidden = false; question(); });
$('suivant').addEventListener('click', function () { phase === 'q' ? reponse() : question(); });
document.addEventListener('keydown', function (e) { if ((e.key === 'ArrowRight' || e.key === ' ') && !$('s-question').hidden) { e.preventDefault(); $('suivant').click(); } });
$('plein').addEventListener('click', function () { document.fullscreenElement ? document.exitFullscreen() : document.documentElement.requestFullscreen && document.documentElement.requestFullscreen(); });
})();
</script>
</body>
</html>

View file

@ -0,0 +1,44 @@
@extends('layouts.vitrine')
@section('titre', 'Ressources')
@section('contenu')
<div style="background:#fff">
<section style="padding:112px 20px 64px">
<div style="max-width:880px;margin:0 auto;text-align:center">
<p id="r-titre-k" style="margin:0;font-size:15px;font-weight:700;color:#1d5cf5;letter-spacing:0.01em">Outil</p>
<h1 id="r-titre" style="margin:20px 0 0;font-size:clamp(40px,6vw,68px);line-height:1.04;font-weight:800;letter-spacing:-0.03em;color:#0b1220;text-wrap:balance">Outil</h1>
<p id="r-probleme" style="margin:28px auto 0;max-width:640px;font-size:20px;line-height:1.6;font-weight:500;color:#374151;text-wrap:pretty"></p>
<div style="margin-top:44px;display:flex;flex-direction:column;align-items:center;gap:14px">
<a id="r-demo" href="#" style="display:inline-flex;align-items:center;height:56px;padding:0 32px;border-radius:999px;background:#0b57d0;color:#fff;font-size:17px;font-weight:700;text-decoration:none">Voir la démo</a>
<p style="margin:0;font-size:14px;font-weight:600;color:#4b5563">Interactive, sans inscription</p>
</div>
</div>
</section>
<section style="padding:0 20px 120px">
<div style="max-width:1080px;margin:0 auto">
<div id="r-video" style="position:relative;aspect-ratio:16/9;width:100%;overflow:hidden;border-radius:24px;background:#f3f4f6;box-shadow:0 1px 2px rgba(15,23,42,.06),0 24px 48px -24px rgba(15,23,42,.18)"></div>
<p id="r-video-legende" style="margin:16px 0 0;text-align:center;font-size:14px;font-weight:600;color:#4b5563"></p>
</div>
</section>
<section style="padding:0 20px 120px">
<ul id="r-points" style="max-width:1080px;margin:0 auto;padding:0;list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:56px 48px"></ul>
</section>
<section style="padding:0 20px 120px">
<div style="max-width:720px;margin:0 auto">
<h2 style="margin:0;font-size:32px;font-weight:800;letter-spacing:-0.02em;color:#0b1220">En trois étapes</h2>
<ol id="r-etapes" style="margin:40px 0 0;padding:0;list-style:none;display:grid;gap:28px"></ol>
</div>
</section>
<section style="padding:96px 20px 128px;border-top:1px solid #e5e7eb">
<div style="max-width:720px;margin:0 auto;text-align:center">
<p id="r-pour" style="margin:0;font-size:15px;font-weight:700;color:#4b5563"></p>
<h2 id="r-accroche-fin" style="margin:16px 0 0;font-size:clamp(28px,4vw,40px);line-height:1.15;font-weight:800;letter-spacing:-0.02em;color:#0b1220;text-wrap:balance"></h2>
<a id="r-demo2" href="#" style="margin-top:36px;display:inline-flex;align-items:center;height:56px;padding:0 32px;border-radius:999px;background:#0b57d0;color:#fff;font-size:17px;font-weight:700;text-decoration:none">Voir la démo</a>
</div>
</section>
<script src="{{ asset('js/ressources.js') }}"></script>
<script>window.URL_VIDEOS = "{{ asset('videos') }}"; window.URL_RESSOURCE = "{{ route('ressource') }}"; window.URL_DEMOS = {"cockpit": "{{ route('cockpit') }}", "espace-eleve": "{{ route('espace.eleve') }}", "vie-scolaire": "{{ route('vie.scolaire') }}", "academie": "{{ route('academie') }}", "cohortes": "{{ route('cohortes') }}", "espace-etablissement": "{{ route('espace.etablissement') }}", "integration": "{{ route('integration') }}", "cours": "{{ route('cours.index') }}", "labs": "{{ route('labs.index') }}", "lab-web": "{{ route('labs.web') }}", "ide": "{{ route('ide') }}", "maison": "{{ route('maison') }}", "bibliotheque": "{{ route('bibliotheque') }}", "banque": "{{ route('banque') }}", "generateur": "{{ route('generateur') }}", "td-imprimable": "{{ route('td.imprimable') }}", "quiz": "{{ route('quiz.projection') }}", "sujet": "{{ route('sujet.creer') }}", "devoirs": "{{ route('devoirs') }}", "correction": "{{ route('correction') }}", "fiche-eleve": "{{ route('fiche.eleve') }}", "messagerie": "{{ route('messagerie') }}", "export": "{{ route('export.ent') }}"};</script>
<script src="{{ asset('js/ressource-page.js') }}"></script>
</div>
@endsection

View file

@ -0,0 +1,19 @@
@extends('layouts.vitrine')
@section('titre', "Salle d'attente")
@section('contenu')
@if ($labSession->etat === \App\Models\LabSession::EN_ATTENTE)
<meta http-equiv="refresh" content="5">
@endif
<div class="mx-auto max-w-2xl px-5 py-20 text-center lg:px-10">
<p class="font-mono text-sm font-semibold">{{ $seance->lab->titre }}</p>
@if ($labSession->etat === \App\Models\LabSession::EN_ATTENTE)
<h1 class="mt-2 text-4xl font-extrabold tracking-tight">En attente que le prof t'admette…</h1>
<p class="mt-4 font-semibold">Cette page se rafraîchit toute seule.</p>
@else
<h1 class="mt-2 text-4xl font-extrabold tracking-tight">Tu es admis·e !</h1>
<p class="mt-4 font-semibold">Le lancement de ta VM arrive dans une prochaine étape du déploiement.</p>
@endif
</div>
@endsection

View file

@ -0,0 +1,32 @@
@extends('layouts.vitrine')
@section('titre', "Salle d'attente")
@section('contenu')
<meta http-equiv="refresh" content="10">
<div class="mx-auto max-w-4xl px-5 py-14 lg:px-10">
<p class="font-mono text-sm font-semibold">{{ $seance->classe->nom }} · {{ $seance->lab->titre }}</p>
<h1 class="mt-1 text-4xl font-extrabold tracking-tight">Salle d'attente</h1>
<p class="mt-2 font-semibold">La page se rafraîchit toutes les 10 secondes.</p>
@if ($seance->labSessions->isEmpty())
<p class="mt-8 font-semibold">Personne n'a encore rejoint la séance.</p>
@else
<ul class="mt-8 grid gap-3">
@foreach ($seance->labSessions as $labSession)
<li class="flex items-center justify-between gap-4 border border-[#e3e5e8] rounded-2xl bg-white p-4">
<span class="font-extrabold">{{ $labSession->eleve->nomAffiche() }}</span>
@if ($labSession->etat === \App\Models\LabSession::EN_ATTENTE)
<form action="{{ route('seances.admettre', [$seance, $labSession]) }}" method="post">
@csrf
<button type="submit" class="inline-flex h-10 items-center rounded-full bg-[#0b57d0] px-4 font-bold text-white">Admettre</button>
</form>
@else
<span class="rounded-lg border border-[#dadce0] bg-[#e6f4ea] px-3 py-1 font-mono text-sm font-bold">Admis</span>
@endif
</li>
@endforeach
</ul>
@endif
</div>
@endsection

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long