# ANMA Intranet — nouvelle appli (Laravel)

## Contexte général

Refonte progressive ("strangler fig") de l'intranet CodeIgniter 4 d'ANMA
(cabinet d'architecture), un outil de production utilisé quotidiennement.
L'ancienne appli (`c:\01-Encours\88-Intranet-ANMA\public_html`, CI4 +
Bootstrap) reste **en prod, non touchée**, pendant qu'on construit celle-ci
module par module. Décision prise explicitement par Frédéric : plus de
Bootstrap/CodeIgniter, tout en **Laravel 12 + Inertia.js v2 + Vue 3 +
Tailwind v3 + shadcn-vue** (scaffoldé via `laravel/vue-starter-kit`).

Dépôt séparé, poussé sur `https://github.com/fredfreefly/anma-laravel`
(privé), branche `main`.

## Qui je suis en train d'aider

Frédéric Trétout (frederic@studiottt.com), Studio TTT — designer web,
seul développeur sur ce projet. À l'aise en PHP (lit/possède le code
CodeIgniter existant), plus récent sur Vue3/Tailwind/Inertia. Donne des
retours directs et précis par capture d'écran ; préfère qu'on **vérifie
réellement dans un navigateur** (agent Playwright) plutôt que de déduire
du code seul — cette méthode a évité plusieurs fausses pistes pendant la
session qui a construit le jalon 1.

## Environnement de dev (Docker / Laravel Sail)

- Nouvelle appli : Sail, `docker compose` généré (`compose.yaml`, pas
  `docker-compose.yml`). Conteneurs : `anma-laravel-laravel.test-1` (app,
  port **8000**), `anma-laravel-mysql-1` (MySQL 8.4, port 3306, db
  `anma_intranet`), `anma-laravel-redis-1`.
- Ancienne appli CI4 tourne **en parallèle**, toujours utile : conteneurs
  `public_html-app-1` (port **8080**), `public_html-mysqldb-1` (MySQL,
  port hôte **3307**, db `intranet`, préfixe de tables `adb_`).
- `WWWUSER=1000`/`WWWGROUP=1000` doivent être définis à la main dans
  `.env` (l'auto-détection Sail ne marche pas sous Windows).
- `.env` réel contient le vrai mot de passe de la base legacy
  (`DB_LEGACY_PASSWORD`) — gitignored, ne jamais committer. `.env.example`
  a la même structure avec ce champ vide.
- Build front : `docker exec anma-laravel-laravel.test-1 npm run build`
  (pas de serveur Vite dev qui tourne en continu pour l'instant — relancer
  ce build après toute modif de `.vue`/`.ts` pour la voir prise en compte).
- Commandes artisan : `docker exec anma-laravel-laravel.test-1 php artisan ...`

## Connexion à la base legacy (import ponctuel uniquement)

`config/database.php` a une connexion secondaire `mysql_legacy` (host
`host.docker.internal`, port `3307`, db `intranet`, préfixe `adb_`,
déjà accessible depuis les conteneurs Sail via `extra_hosts` dans
`compose.yaml`). **Utilisée uniquement par la commande d'import**
(`php artisan import:legacy-projets`, voir plus bas), jamais pour du
trafic applicatif normal.

## État d'avancement : Jalon 1 "Module Projets" — TERMINÉ

Liste + fiche projet sur données réelles (671 projets), pas encore
d'upload/édition/filtres avancés. Poussé sur GitHub (commit `008a594`).

**Importé depuis la base legacy** (idempotent par colonne `legacy_id`,
vérifié en le relançant deux fois sans doublon) :
671 projets, 804 entreprises, 641 listes déroulantes, 49 970 médias,
47 453 liaisons projet↔média.

**Fichiers clés créés/modifiés ce jalon :**
- `database/migrations/2026_08_23_*` — 6 nouvelles tables (entreprises,
  listes_deroulantes, media, projets, projet_media, projet_favoris)
- `app/Models/{Projet,Entreprise,Media,ListeDeroulante,ProjetMedia,ProjetFavori}.php`
- `app/Console/Commands/ImportLegacyProjets.php`
- `app/Http/Controllers/{ProjetController,ProjetFavoriController}.php`
- `routes/web.php` — routes `/projets`, `/projets/{projet}`,
  `PATCH /projets/{projet}/favori` (groupe `auth`)
- `resources/js/pages/Projets/{Index,Show}.vue`
- `resources/js/components/ui/badge/` — composant Badge (manquait du
  starter kit, créé sur le modèle CVA de Button)
- `resources/js/components/{NavMain,AppSidebar}.vue` — **bug corrigé** :
  le starter kit avait un lien Dashboard cassé dans la sidebar
  (`NavMain.vue` définissait son propre type `NavItem` avec `url`, alors
  qu'`AppSidebar.vue` fournissait `href` via `@/types`) ; lien Projets
  ajouté au passage
- `config/services.php` — `services.legacy_app.url` (env `LEGACY_APP_URL`,
  défaut `http://localhost:8080`) : les images pointent vers l'ancienne
  appli plutôt que d'être copiées (voir bug connu ci-dessous)

**Vérifié en navigateur réel** (agent Playwright, compte de dev
`frederic@studiottt.com` / `password`, créé directement en base — base de
dev locale vide, sans risque) : navigation sidebar, recherche (debounce +
query param `q`), pagination, toggle favori (optimiste côté serveur via
`router.patch` Inertia, pas de flicker), fiche détail avec les 4 cartes
groupées (Identification, Localisation, Maître d'ouvrage, Montants &
surfaces), galerie de visuels.

## Bug connu, contourné (pas corrigé) : stockage média legacy incohérent

Certains fichiers `app_files/projets/*` de l'ancienne appli sont stockés
**compressés en `.gz`** ou dans une arborescence différente de celle que
les colonnes `path_to_vignette`/`path_to_moyenne` en base laissent
supposer (contrairement à `app_files/contacts/*`, qui sont des fichiers
plats et servent très bien). Quand le fichier référencé n'existe pas tel
quel, le `.htaccess` de l'ancienne appli tombe en fallback sur
`index.php`, et son filtre global `logged-in` (`app/Config/Filters.php`)
redirige alors vers `/auth/login` — donc une `<img>` pointée dessus
échoue silencieusement (icône cassée / bloqué ORB par le navigateur).//
L'ancienne appli a d'ailleurs déjà une commande `CheckMediaIntegrity`,
donc ce n'est pas une découverte : c'est de la dette connue.

**Contournement appliqué** (dans `Projets/Index.vue` et `Projets/Show.vue`) :
un handler `@error` sur chaque `<img>` bascule silencieusement sur le
placeholder gris existant (`PlaceholderPattern.vue`) au lieu d'afficher
une icône cassée. La vraie correction (décompresser les `.gz`, harmoniser
les chemins, ou migrer vers S3 — déjà anticipé comme chantier séparé)
**n'a pas été faite**.

## Explicitement repoussé (pas oublié, ne pas réintroduire sans qu'on demande)

`adb_projets_moas` many-to-many maîtres d'ouvrage (le jalon 1 utilise
directement l'ancienne FK simple `id_maitre_d_ouvrage`), table
`media_categories` relationnelle complète, intervenants / programmes /
mots-clés / certifications, filtres avancés (dropdowns), upload, édition,
réimport des favoris (nécessite une correspondance future entre les
anciens comptes IonAuth et les nouveaux `users` Laravel), vrai stockage
S3, tag visuel IA, visionneuse BIM, intégration Microsoft 365.

## Plan détaillé du jalon 1

Le plan approuvé complet (contexte, découvertes sur le schéma legacy,
étapes, checklist de vérification) est sur disque :
`C:\Users\frede\.claude\plans\greedy-imagining-raccoon.md`
