IT-Stock/app/templates/scan.html

127 lines
5 KiB
HTML
Raw Normal View History

{% 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 code_barre_introuvable %}
{#
Code scanné mais aucun matériel ne le porte : au lieu d'un simple
message d'erreur, on propose le même formulaire de création rapide que
sur /materiels, avec le code-barre déjà rempli, pour ne pas avoir à
quitter l'écran de scan.
#}
<article class="etiquette-resultat etiquette-creation">
<div class="rayures-code-barre etiquette-rayures" aria-hidden="true"></div>
<p class="etiquette-fil">Code inconnu</p>
<h2 class="etiquette-nom">« {{ code_barre_introuvable }} »</h2>
{% if categories_aplaties %}
<form method="post" action="/scan/creer" class="formulaire-grille etiquette-formulaire">
<input type="hidden" name="code_barre" value="{{ code_barre_introuvable }}">
<label>Nom <input type="text" name="nom" required autofocus></label>
<label>Catégorie
<select name="categorie_id" required>
{% for profondeur, categorie in categories_aplaties %}
<option value="{{ categorie.id }}">{{ "— " * profondeur }}{{ categorie.nom }}</option>
{% endfor %}
</select>
</label>
<label>Quantité initiale <input type="number" name="quantite" value="0" min="0"></label>
<label>Seuil d'alerte <input type="number" name="seuil_alerte" min="0"></label>
<button type="submit">Créer et ajouter au stock</button>
</form>
{% else %}
<p class="etiquette-sous-titre">
Créez d'abord une <a href="/categories">catégorie</a> avant de pouvoir créer ce matériel.
</p>
{% endif %}
</article>
{% 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 %}
{#
Deux façons distinctes d'agir sur le stock, pour ne pas mélanger les
deux gestes : "ajuster" applique un delta (une quantité reçue ou
sortie, pas forcément 1) ; "définir" corrige directement le total
(utile après un inventaire physique, sans calculer d'écart).
#}
<div class="etiquette-controles">
<form method="post" action="/scan/{{ materiel.id }}/ajuster" class="formulaire-ajustement">
<label class="etiquette-champ-quantite">
Quantité à ajuster
<input type="number" name="quantite" value="1" min="1" required>
</label>
<div class="etiquette-actions">
<button type="submit" name="sens" value="retirer" class="bouton-scan bouton-sortie"> Retirer</button>
<button type="submit" name="sens" value="ajouter" class="bouton-scan bouton-reception">+ Ajouter</button>
</div>
</form>
<form method="post" action="/scan/{{ materiel.id }}/definir" class="formulaire-definir">
<label class="etiquette-champ-quantite">
Définir le stock à
<input type="number" name="quantite" value="{{ materiel.quantite }}" min="0" required>
</label>
<button type="submit">Enregistrer</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 %}