All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2s
93 lines
6.4 KiB
Markdown
93 lines
6.4 KiB
Markdown
---
|
|
title: 'Reconstruire le parcours utilisateur glossaire'
|
|
type: 'refactor'
|
|
created: '2026-05-16'
|
|
status: 'draft'
|
|
context: []
|
|
---
|
|
|
|
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
|
|
|
|
## Intent
|
|
|
|
**Problem:** L'utilisateur Pro voit DEUX liens "Glossaires" dans la sidebar à cause d'un doublon dans constants.ts (`baseNavItems` contient un item glossary + `proNavItem` est aussi un item glossary → `getNavItems(isPro=true)` retourne les deux). Le GlossarySelector sur la page de traduction est un petit dropdown caché, visible uniquement pour les Pro, sans label ni indication de son rôle. L'utilisateur ne comprend pas le cheminement: créer un glossaire → le sélectionner → traduire.
|
|
|
|
**Approach:** Corriger le doublon de navigation, rendre le GlossarySelector visible et explicatif pour TOUS les utilisateurs (les Free voient un badge "Pro"), supprimer la page Context obsolète, et ajouter un lien clair entre la page Glossaires et la page Traduction.
|
|
|
|
## Boundaries & Constraints
|
|
|
|
**Always:**
|
|
- Un seul lien "Glossaires" dans la sidebar, jamais deux
|
|
- Le GlossarySelector doit être visible sur la page de traduction pour TOUS les utilisateurs connectés
|
|
- Les utilisateurs Free doivent voir le sélecteur grisé avec un badge "Pro" (pas caché)
|
|
- Le system prompt reste sur la page Glossaires (déjà fusionné)
|
|
- Backend inchangé — seul le frontend est touché
|
|
|
|
**Ask First:** Aucune décision ambiguë — tout est clair.
|
|
|
|
**Never:**
|
|
- Ne pas toucher aux routes API ou au backend
|
|
- Ne pas recréer une page Context séparée
|
|
- Ne pas supprimer les presets professionnels (HVAC, IT, etc.)
|
|
|
|
## I/O & Edge-Case Matrix
|
|
|
|
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|
|
|----------|--------------|---------------------------|----------------|
|
|
| Utilisateur Pro voit la sidebar | isPro=true, page quelconque | Un seul lien "Glossaires" dans le menu | N/A |
|
|
| Utilisateur Free voit la sidebar | isPro=false | Aucun lien Glossaires (proOnly=true) | N/A |
|
|
| Utilisateur Free sur page traduction | isPro=false, mode LLM | GlossarySelector visible mais grisé, badge "Pro", clic → tooltip "Upgrade required" | N/A |
|
|
| Utilisateur Pro sur page traduction | isPro=true | GlossarySelector fonctionnel, dropdown avec ses glossaries | Toast si fetch échoue |
|
|
| Utilisateur avec 0 glossaries | glossaries=[] | Sélecteur affiche "Aucun glossaire — Créez-en un" avec lien vers /dashboard/glossaries | N/A |
|
|
| Utilisateur accède /dashboard/context par URL | N'importe quel état | Redirige vers /dashboard/glossaries | N/A |
|
|
|
|
</frozen-after-approval>
|
|
|
|
## Code Map
|
|
|
|
- `frontend/src/app/dashboard/constants.ts` -- Navigation: contient le doublon glossary (baseNavItems + proNavItem)
|
|
- `frontend/src/app/dashboard/translate/page.tsx` -- Page traduction: emplacement du GlossarySelector, conditions de visibilité
|
|
- `frontend/src/app/dashboard/translate/GlossarySelector.tsx` -- Composant dropdown de sélection de glossaire
|
|
- `frontend/src/app/dashboard/translate/useTranslationConfig.ts` -- Hook qui gère glossaryId
|
|
- `frontend/src/app/dashboard/context/page.tsx` -- Page obsolète à supprimer/remplacer par redirect
|
|
- `frontend/src/app/dashboard/glossaries/page.tsx` -- Page Glossaries fusionnée (OK, pas toucher)
|
|
|
|
## Tasks & Acceptance
|
|
|
|
**Execution:**
|
|
- [ ] `frontend/src/app/dashboard/constants.ts` -- Supprimer `proNavItem` et la fonction `getNavItems`, remettre les items proOnly dans `baseNavItems` avec le flag proOnly. Garder exactement 4 items: Translate, Profile, Glossaries (proOnly), API Keys (proOnly). -- Un seul lien glossary dans la sidebar, jamais de doublon.
|
|
- [ ] `frontend/src/app/dashboard/translate/GlossarySelector.tsx` -- Refactoriser: toujours rendre le composant visible (même pour Free). Si l'utilisateur n'est pas Pro: afficher le dropdown grisé avec badge "Pro" et tooltip "Upgrade required". Si l'utilisateur est Pro mais n'a pas de glossaries: afficher un message "Aucun glossaire" avec un lien cliquable vers /dashboard/glossaries. Ajouter le composant `useUser` ou recevoir `isPro` en prop. -- Tous les utilisateurs voient le sélecteur, les Free comprennent que c'est Pro.
|
|
- [ ] `frontend/src/app/dashboard/translate/page.tsx` -- Retirer la condition `config.isPro &&` autour du GlossarySelector. Placer le GlossarySelector à un endroit visible dans le panneau de config (entre ProviderSelector et le bouton Traduire). S'assurer que `isPro` est passé en prop au GlossarySelector. -- Le sélecteur est visible pour tous, pas caché derrière une condition.
|
|
- [ ] `frontend/src/app/dashboard/context/page.tsx` -- Remplacer tout le contenu par un redirect côté client vers `/dashboard/glossaries` (`useRouter` + `useEffect` ou `router.replace`). -- L'ancienne URL redirige proprement.
|
|
|
|
**Acceptance Criteria:**
|
|
- Given un utilisateur Pro connecté, when il regarde la sidebar, then il voit exactement UN lien "Glossaires"
|
|
- Given un utilisateur Free connecté, when il va sur la page de traduction, then il voit le GlossarySelector grisé avec un badge "Pro"
|
|
- Given un utilisateur Pro avec des glossaries, when il va sur la page de traduction, then il peut sélectionner un glossary dans le dropdown
|
|
- Given un utilisateur Pro sans glossary, when il va sur la page de traduction, then le sélecteur affiche "Aucun glossaire" avec un lien vers la page Glossaires
|
|
- Given n'importe quel utilisateur, when il accède /dashboard/context, then il est redirigé vers /dashboard/glossaries
|
|
|
|
## Spec Change Log
|
|
|
|
## Design Notes
|
|
|
|
**Parcours utilisateur attendu:**
|
|
1. L'utilisateur clique sur "Glossaires" dans la sidebar → arrive sur la page unifiée (system prompt + presets + CRUD glossaires)
|
|
2. L'utilisateur crée ou charge un glossaire (manuel, CSV, template)
|
|
3. L'utilisateur va sur "Traduire" → voit le sélecteur "Glossaire" en clair → sélectionne son glossaire → traduit
|
|
4. Le glossaire est appliqué automatiquement à la traduction
|
|
|
|
Le GlossarySelector doit recevoir `isPro` et `disabled` en props. Si `!isPro`, le composant se rend en mode "locked" (grisé + badge Pro). Si `isPro && glossaries.length === 0`, afficher un CTA vers la page glossaires.
|
|
|
|
## Verification
|
|
|
|
**Commands:**
|
|
- `cd frontend && npx next build --webpack` -- expected: build réussi sans erreurs TypeScript
|
|
|
|
**Manual checks:**
|
|
- Sidebar Pro: exactement un lien Glossaires
|
|
- Sidebar Free: aucun lien Glossaires
|
|
- Page traduction Free: GlossarySelector visible mais grisé avec badge Pro
|
|
- Page traduction Pro: GlossarySelector fonctionnel
|
|
- URL /dashboard/context: redirige vers /dashboard/glossaries
|