Catégorie/SousCategorie fusionnées en un seul modèle auto-référencé (parent_id), pour permettre une imbrication sans limite de niveaux. Les listings matériels/catégories/destinataires passent en lignes repliées (<details>) avec recherche côté serveur, ce qui corrige le débordement horizontal du tableau tout-en-input et reste utilisable sur de longues listes. Style de l'écran de scan également retravaillé (frontend-design).
80 lines
2.7 KiB
HTML
80 lines
2.7 KiB
HTML
{% extends "base.html" %}
|
||
{% block titre %}Scanner - Gestion de stock IT{% endblock %}
|
||
{% block contenu %}
|
||
<section class="scanner">
|
||
<header class="scanner-entete">
|
||
<p class="scanner-eyebrow">Poste de scan</p>
|
||
<h1>Identifier un matériel</h1>
|
||
</header>
|
||
|
||
{#
|
||
Un seul champ dans un <form> : la douchette tape le code puis Entrée,
|
||
ce qui soumet le formulaire nativement (aucun JavaScript nécessaire
|
||
pour capter le scan). La "ligne laser" sous le champ ne s'anime que
|
||
lorsqu'il a le focus (voir .scanner-champ:focus + .laser-ligne dans
|
||
style.css) : un clin d'œil au faisceau de la douchette physique.
|
||
#}
|
||
<form method="post" action="/scan" class="scanner-formulaire">
|
||
<label for="champ-scan" class="scanner-label">Code-barre</label>
|
||
<input
|
||
type="text"
|
||
name="code_barre"
|
||
id="champ-scan"
|
||
class="scanner-champ"
|
||
placeholder="En attente de scan…"
|
||
autocomplete="off"
|
||
autofocus
|
||
required
|
||
>
|
||
<div class="laser-ligne" aria-hidden="true"></div>
|
||
</form>
|
||
|
||
{% if erreur %}
|
||
<p class="etiquette-erreur">{{ erreur }}</p>
|
||
{% endif %}
|
||
|
||
{% if materiel %}
|
||
{% set sous_seuil = materiel.seuil_alerte is not none and materiel.quantite < materiel.seuil_alerte %}
|
||
<article class="etiquette-resultat">
|
||
<div class="rayures-code-barre etiquette-rayures" aria-hidden="true"></div>
|
||
|
||
<p class="etiquette-fil">{{ materiel.categorie.chemin() }}</p>
|
||
<h2 class="etiquette-nom">{{ materiel.nom }}</h2>
|
||
|
||
<div class="etiquette-quantite">
|
||
<span class="etiquette-nombre">{{ materiel.quantite }}</span>
|
||
<span class="etiquette-unite">en stock</span>
|
||
</div>
|
||
|
||
{% if materiel.seuil_alerte is not none %}
|
||
<p class="etiquette-statut">
|
||
<span class="statut-puce {{ 'statut-bas' if sous_seuil else 'statut-ok' }}"></span>
|
||
{% if sous_seuil %}
|
||
Sous le seuil d'alerte ({{ materiel.seuil_alerte }})
|
||
{% else %}
|
||
Seuil d'alerte : {{ materiel.seuil_alerte }}
|
||
{% endif %}
|
||
</p>
|
||
{% endif %}
|
||
|
||
<div class="etiquette-actions">
|
||
<form method="post" action="/scan/{{ materiel.id }}/ajuster">
|
||
<input type="hidden" name="delta" value="-1">
|
||
<button type="submit" class="bouton-scan bouton-sortie">− Sortie</button>
|
||
</form>
|
||
<form method="post" action="/scan/{{ materiel.id }}/ajuster">
|
||
<input type="hidden" name="delta" value="1">
|
||
<button type="submit" class="bouton-scan bouton-reception">+ Réception</button>
|
||
</form>
|
||
</div>
|
||
</article>
|
||
{% endif %}
|
||
</section>
|
||
|
||
<script>
|
||
// Remet le focus sur le champ de scan à chaque affichage de la page,
|
||
// pour pouvoir enchaîner les scans sans avoir à cliquer dans le champ.
|
||
document.getElementById("champ-scan").focus();
|
||
</script>
|
||
{% endblock %}
|