---
suivi: 1068
date: 2026-07-29
sujet: Filtres programme et projet sur Mes tâches
chantier: taches_suivi
type: feature
statut: poussé
hash: d3ed1c3f
fichiers:
  - resources/js/Pages/MesTaches/Index.vue
  - app/Http/Controllers/MesTachesController.php
  - app/Models/User.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
  - docs/suivi/SUIVI_1068_filtres_programme_projet_mes_taches.md
---

## PROMPT ENVOYÉ

SUIVI #1068 — deux sélecteurs FILTRE Programme et Projet sur `/mes-taches`, modèle
ÉTIQUETTE, mémorisés via `users.preferences`, cumulables. Parade C1. Pas d’élargissement
de visibilité. Options = présents dans le jeu. Ops exclues si filtre projet.

## SYNTHÈSE

### Où filtrent
- ÉTIQUETTE / PROGRAMME / PROJET : **FRONT** (comme #1055 étiquette), sur `displayItems`.
- FILTRE en retard / TYPE / terminées / inclure programmes : **BACK** (inchangé).
- Regroupement COLONNES : **FRONT** (#1047) — cumulable avec les filtres.

### Options sélecteurs
Uniquement programmes / projets **présents** dans `displayItemsBase` (jeu déjà visible).
Justif. : éviter 13 programmes vides. Programme via `isEtiquetteProgramme` (C1) +
`programme_id` (couvre virtuelle #1051). Projet via `projet_id` / `projet.nom`.

### Suivi + ops
Filtre programme : étiquettes `type === 'programme'` (réelles suivi + virtuelles ops).
Filtre projet : ops sans `projet_id` → **disparaissent**.

### Préférences (#1058 réutilisé)
- `mes_taches_filtre_programme_id`
- `mes_taches_filtre_projet_id`
Pas de second mécanisme. Compteurs `resume` : BACK, hors filtres front (comme étiquette).

### Visibilité
Aucun changement de scope SQL / policies. Filtres d’affichage uniquement.

## DÉPLOIEMENT-TEST

```bash
git pull origin main
find app/ -name "*.php" -exec touch {} +
php artisan optimize:clear
php artisan journal:sync
# pas de migrate ; pas de route:clear
```

## LEÇON
« Regrouper par X » et « filtrer sur un X » sont deux besoins distincts. Le rattachement
programme étant asymétrique (étiquette réelle vs virtuelle facture), tout filtre programme
doit être testé sur les DEUX types sous peine de n’en filtrer qu’un.

Complément #1070 :
- une préférence mémorisée doit distinguer **« valeur vide choisie »** de **« pas de valeur
  enregistrée »**, sinon l’utilisateur ne peut plus jamais revenir à l’état neutre ;
- construire les options d’un filtre à partir du jeu **déjà filtré** (ou avec `value:null`
  incompatible Select) rend deux filtres mutuellement exclusifs / impossibles à remettre
  à « Tous » : les options doivent venir du jeu visible, pas du jeu affiché, et « Tous »
  doit envoyer une sentinelle explicite (`0`) qui **efface** la clé de préférence.
