@php
/**
* Barre de filtres de l'index commandes.
*
* Chaque pastille est un lien : l'url porte l'état complet de l'écran, il
* reste donc partageable et le bouton "précédent" du navigateur fonctionne.
* Cliquer une pastille active la désactive.
*
* Attendus : $stats (compteurs), $etats / $statuts / $priorites (facettes
* ordonnées par le contrôleur), $types (facette des types, déjà libellée
* et triée par l'api), $filtres (filtres actifs), $q, $tri.
*/
// Construit l'url en repartant des filtres courants, page remise à 1.
// Le tri suit les filtres : changer de facette ne doit pas faire perdre
// l'ordre qu'on vient de choisir.
$lien = function (array $modifs) use ($filtres, $q, $tri) {
$params = $filtres;
if ($tri !== '') {
$params['tri'] = $tri;
}
foreach ($modifs as $cle => $valeur) {
if ($valeur === null) {
unset($params[$cle]);
} else {
$params[$cle] = $valeur;
}
}
if ($q !== '') {
$params['q'] = $q;
}
return route('commandes.index', $params);
};
@endphp
{{-- ---------------------------- État ----------------------------
Ordre, libellés et couleurs viennent de config/commandes.php : c'est le
déroulé de l'atelier, aligné sur le bandeau du logiciel métier. --}}
{{ __('État') }}
@foreach ($etats as $etat)
@php
$actif = ($filtres['etat'] ?? null) === $etat['code'];
// Un état vide ne mène nulle part : on le montre pour garder
// la barre stable, mais on ne le rend pas cliquable.
$vide = $etat['count'] === 0 && !$actif;
// Écarté par le tri par échéance (une commande arrivée n'en a
// plus) : il se montre avec son vrai compte, et s'ouvre en tri
// récent, où il a quelque chose à montrer.
$ecarte = !empty($etat['ecarte']);
@endphp
@if ($ecarte)
@endif
{{ $etat['label'] }}
{{ $etat['count'] }}
@endforeach
{{-- Le total ferme la barre, comme dans le logiciel --}}
{{ __('TOTAL') }}
{{ $stats['total'] }}
{{-- ------------------- Filtres secondaires : une ligne de menus -------------------
Six rangées de pastilles couvraient la moitié de l'écran avant la première
commande. Les états gardent leurs pastilles, on s'en sert sans arrêt ; le
reste passe en menus sur une ligne, et ce qui est actif revient en puces
qu'on retire d'un clic, juste en dessous.
Chaque entrée reste un lien construit par $lien() : l'url porte toujours
l'état complet de l'écran, et un menu n'est qu'une autre façon de montrer
les mêmes pastilles, compteurs compris.
Les échéances sont cumulatives et comprennent le retard : « sous 7 jours »,
c'est tout ce qui doit être traité d'ici là. La date prévisionnelle est
calculée par l'api, elle n'est stockée nulle part.
« Sans type » n'est pas un type mais son absence : `type_id=0` dans l'url,
un `IS NULL` côté api. `empty()` est à proscrire sur ce filtre, il vaut '0'. --}}
@php
$typeActif = $filtres['type_id'] ?? null;
$sansType = (int) ($stats['sans_type'] ?? 0);
$options = [
// « MAJ plan » et « Incomplet » ouvrent la liste : ce sont des
// anomalies du process, les deux premières choses qu'on vient chercher.
'maj_plan' => [__('MAJ plan'), 'bi-file-earmark-diff'],
'incomplet' => [__('Incomplet'), 'bi-exclamation-triangle'],
'maconnerie' => [__('Maçonnerie'), 'bi-bricks'],
'cintrage' => [__('Cintrage'), 'bi-bezier2'],
'decoupe' => [__('Découpe'), 'bi-scissors'],
'accessoire' => [__('Accessoire'), 'bi-tools'],
'negoce' => [__('Négoce'), 'bi-shop'],
];
// Les filtres actifs, en puces : libellé et lien qui le retire. Construit
// une fois ici, relu par le bouton de chaque menu et par la ligne de puces.
$puces = [];
$echeanceActive = $filtres['echeance'] ?? null;
if ($echeanceActive !== null && ($meta = config("commandes.echeances.$echeanceActive"))) {
$puces['echeance'] = __($meta['label']);
}
foreach (['priorite' => $priorites, 'statut' => $statuts] as $champ => $facette) {
foreach ($facette as $f) {
if (($filtres[$champ] ?? null) === $f['code']) {
$puces[$champ] = $f['label'];
}
}
}
if ($typeActif === '0') {
$puces['type_id'] = __('Sans type');
} else {
foreach ($types as $t) {
if ($typeActif === $t['code']) {
$puces['type_id'] = \App\Helpers\CommandeHelper::nomTraduit($t['label']);
}
}
}
$optionsActives = array_filter($options, fn ($meta, $champ) => !empty($filtres[$champ]), ARRAY_FILTER_USE_BOTH);
foreach ($optionsActives as $champ => $meta) {
$puces[$champ] = $meta[0];
}
// Les filtres des liens du tableau de bord : pas de menu pour eux,
// seulement la puce qui dit ce qu'on regarde et permet d'en sortir.
if (!empty($filtres['vue'])) {
$vues = collect(explode(',', $filtres['vue']))->map(function ($code) {
$libelle = \App\Services\Acportail\TableauBordService::libelleVue($code);
return in_array($code, \App\Services\Acportail\TableauBordService::VUES_ANOMALIES, true)
? __('Anomalie : :quoi', ['quoi' => $libelle])
: $libelle;
});
$puces['vue'] = $vues->implode(' · ');
}
if (isset($filtres['laqueur'])) {
$puces['laqueur'] = __('Laqueur : :quoi', [
'quoi' => \App\Helpers\CommandeHelper::laqueur((int) $filtres['laqueur'] ?: null, __('Non renseigné')),
]);
}
if (isset($filtres['fautif'])) {
$puces['fautif'] = __('Reprise, fautif : :quoi', [
'quoi' => \App\Helpers\CommandeHelper::fautif((int) $filtres['fautif'] ?: null, __('Non renseigné')),
]);
}
if (!empty($filtres['modele'])) {
$puces['modele'] = __('Modèle : :quoi', ['quoi' => \App\Helpers\CommandeHelper::nomTraduit($filtres['modele'], $filtres['modele'])]);
}
if (!empty($filtres['couleur'])) {
$puces['couleur'] = __('Couleur : :quoi', ['quoi' => \App\Helpers\CommandeHelper::couleur($filtres['couleur'], $filtres['couleur'])]);
}
// Le tri n'est pas un filtre : il ne retire aucune ligne, il remonte les
// plus pressées. Filtrer sur une échéance l'active côté api sans qu'on le
// demande ; le bouton le montre, et reste cliquable pour revenir à l'ordre
// par id — le tri explicite prime.
$triImplicite = $tri === '' && !empty($filtres['echeance']);
$triEcheance = $tri === 'echeance' || $triImplicite;
$bascule = $triEcheance
? ($triImplicite || !empty($filtres['echeance']) ? 'recent' : null)
: 'echeance';
@endphp
{{-- Les filtres actifs, chacun retirable d'un clic --}}
@if ($puces || $q !== '')
@endif