# Story 4.8: Page Translation - Progress & Download

Status: done

## Story

En tant qu'**utilisateur**,
Je veux **voir la progression de la traduction en temps réel et télécharger le fichier traduit**,
de sorte que **je sache quand mon fichier est prêt et puisse l'utiliser**.

## Acceptance Criteria

1. **Submit Translation**: Au clic sur "Translate", POST vers `/api/v1/translate` avec `file`, `source_lang`, `target_lang`, `mode`, `provider` (si LLM)
2. **Job ID Storage**: Stocker le `job_id` retourné (202 response: `{data: {id, status: "processing"}, meta: {...}}`)
3. **Progress Polling**: Poll `GET /api/v1/translations/{job_id}` toutes les 2 secondes pendant `status === "processing"`
4. **Progress Display**: Afficher progress bar (0-100%), `current_step`, et temps restant estimé (`meta.estimated_remaining_seconds`)
5. **Status Transitions**: `processing` → `completed` (succès) ou `failed` (erreur)
6. **Error Display**: Si `failed`, afficher `error_message` du backend avec toast notification
7. **Download Button**: Quand `completed`, afficher bouton "Download" qui GET `/api/v1/download/{job_id}`
8. **Download Filename**: Header `Content-Disposition` fourni par backend → `{original_name}_translated.{ext}`
9. **Success Toast**: Afficher confirmation après téléchargement réussi
10. **State Reset**: Option "New Translation" pour réinitialiser et uploader un nouveau fichier
11. **Merge Directive**: UI Progress depuis `frontend/src/components/file-uploader.tsx` (lignes 592-609)
12. **Colocation**: Composants/hooks/types dans `frontend/src/app/dashboard/translate/`

## Tasks / Subtasks

- [x] **Task 1: Étendre types.ts** (AC: #1, #2)
  - [x] 1.1 Ajouter `TranslationJob`, `TranslationStatus`, `TranslationProgress`
  - [x] 1.2 Ajouter `UseTranslationSubmitReturn` interface

- [x] **Task 2: Créer useTranslationSubmit.ts hook** (AC: #1, #2, #3, #4, #5)
  - [x] 2.1 State: `jobId`, `status`, `progress`, `currentStep`, `error`, `estimatedRemaining`
  - [x] 2.2 `submitTranslation(file, config)`: POST `/api/v1/translate` → return job_id
  - [x] 2.3 `pollProgress()`: setInterval 2s → GET `/api/v1/translations/{job_id}`
  - [x] 2.4 Cleanup interval on unmount ou quand status !== "processing"
  - [x] 2.5 Return: `{ submitTranslation, jobId, status, progress, currentStep, error, estimatedRemaining, reset }`

- [x] **Task 3: Créer TranslationProgress.tsx** (AC: #4, #6)
  - [x] 3.1 Props: `progress`, `currentStep`, `estimatedRemaining`, `error`
  - [x] 3.2 Progress bar avec pourcentage (shadcn/ui Progress)
  - [x] 3.3 Afficher `current_step` textuel (ex: "Translating slide 5/10")
  - [x] 3.4 Afficher temps restant formaté (ex: "2 min remaining")
  - [x] 3.5 Error state: message rouge si `status === "failed"`
  - [x] 3.6 Copier styles depuis `file-uploader.tsx` (lignes 592-609)

- [x] **Task 4: Créer TranslationComplete.tsx** (AC: #7, #8, #9)
  - [x] 4.1 Props: `jobId`, `fileName`, `onNewTranslation`
  - [x] 4.2 Download button: GET `/api/v1/download/{job_id}` → trigger browser download
  - [x] 4.3 Success toast après download
  - [x] 4.4 "New Translation" button → callback `onNewTranslation`
  - [x] 4.5 Checkmark icon + message "Translation Complete!"
  - [x] 4.6 Copier styles depuis `file-uploader.tsx` (lignes 627-649)

- [x] **Task 5: Modifier page.tsx pour intégrer le flow complet** (AC: #1, #10)
  - [x] 5.1 State flow: Upload → Config → Submit → Progress → Complete
  - [x] 5.2 Intégrer `useTranslationSubmit` hook
  - [x] 5.3 Conditionnel: afficher Progress si `status === "processing"`
  - [x] 5.4 Conditionnel: afficher Complete si `status === "completed"`
  - [x] 5.5 Conditionnel: afficher Error si `status === "failed"`
  - [x] 5.6 `handleTranslate` → `submitTranslation(file, config.getConfig())`
  - [x] 5.7 `handleNewTranslation` → reset all states

- [x] **Task 6: Vérifier le build et tester** (AC: Tous)
  - [x] 6.1 `npm run build` → 0 erreurs TypeScript
  - [x] 6.2 Tester submit translation → job_id retourné
  - [x] 6.3 Tester polling progress → progress bar updates
  - [x] 6.4 Tester download → fichier téléchargé
  - [x] 6.5 Tester error handling → message affiché
  - [x] 6.6 Tester new translation → reset complet

## Dev Notes

### 🏗️ Stack Technique

| Technologie | Version |
|-------------|---------|
| Next.js | 16.0.6 (App Router) |
| React | 19.2.0 |
| TanStack Query | v5.90.21 (optionnel - polling manuel OK) |
| Tailwind CSS | configuré |
| Lucide React | disponible |
| shadcn/ui | Progress, Button, Card, Toast |

### 📁 Structure Cible (Colocation Pattern)

```
frontend/src/app/dashboard/translate/
├── page.tsx                    # Existant — à modifier
├── types.ts                    # Existant — à étendre
├── useFileUpload.ts            # Existant — pas de modif
├── FileDropZone.tsx            # Existant — pas de modif
├── FilePreview.tsx             # Existant — pas de modif
├── useTranslationConfig.ts     # Existant — pas de modif
├── LanguageSelector.tsx        # Existant — pas de modif
├── TranslationModeToggle.tsx   # Existant — pas de modif
├── ProviderSelector.tsx        # Existant — pas de modif
├── useTranslationSubmit.ts     # 🆕 Hook submit + polling
├── TranslationProgress.tsx     # 🆕 Progress bar + status
└── TranslationComplete.tsx     # 🆕 Download + success
```

**⚠️ Règle absolue (architecture.md):**
```
🚨 FICHIERS SPÉCIAUX: page.tsx, layout.tsx → TOUJOURS minuscules
🚨 COLOCATION: Components/hooks/types dans le dossier de leur page
```

### 🔗 API Endpoints Backend (Déjà implémentés)

| Endpoint | Méthode | Request | Response |
|----------|---------|---------|----------|
| `/api/v1/translate` | POST | FormData: file, source_lang, target_lang, mode, provider | 202: `{data: {id, status: "processing"}, meta: {rate_limit_remaining}}` |
| `/api/v1/translations/{job_id}` | GET | — | `{data: {id, status, progress_percent, current_step, ...}, meta: {estimated_remaining_seconds}}` |
| `/api/v1/download/{job_id}` | GET | — | Binary file + Content-Disposition header |

### References

- [Source: _bmad-output/planning-artifacts/epics.md#Story-4.8] — Story requirements
- [Source: _bmad-output/planning-artifacts/architecture.md#Frontend-Architecture] — TanStack Query + colocation
- [Source: _bmad-output/planning-artifacts/architecture.md#API-Response-Formats] — Format réponse API
- [Source: routes/translate_routes.py#L1064-1151] — GET /api/v1/translations/{job_id} endpoint
- [Source: routes/translate_routes.py#L1188-1317] — GET /api/v1/download/{job_id} endpoint
- [Source: frontend/src/components/file-uploader.tsx#L592-649] — UI Progress + Download patterns
- [Source: _bmad-output/implementation-artifacts/4-7-page-translation-configuration.md] — Context config, types existants

## Dev Agent Record

### Agent Model Used

Claude Sonnet 4 (claude-sonnet-4@20250514)

### Debug Log References

N/A

### Completion Notes List

- ✅ Étendu types.ts avec TranslationStatus, TranslationJob, TranslationSubmitResponse, TranslationStatusResponse, UseTranslationSubmitReturn
- ✅ Créé useTranslationSubmit.ts hook avec submitTranslation, pollProgress (2s interval), cleanup on unmount, reset
- ✅ Créé TranslationProgress.tsx avec progress bar (shadcn/ui Progress), current_step display, temps restant formaté, error state
- ✅ Créé TranslationComplete.tsx avec download button (GET /api/v1/download), success toast, "New Translation" button
- ✅ Modifié page.tsx pour intégrer le flow complet: Upload → Config → Submit → Progress → Complete/Failed
- ✅ Build Next.js réussi (0 erreurs TypeScript)

### File List

**Fichiers créés:**
- frontend/src/app/dashboard/translate/useTranslationSubmit.ts
- frontend/src/app/dashboard/translate/TranslationProgress.tsx
- frontend/src/app/dashboard/translate/TranslationComplete.tsx

**Fichiers modifiés:**
- frontend/src/app/dashboard/translate/types.ts
- frontend/src/app/dashboard/translate/page.tsx
- _bmad-output/implementation-artifacts/sprint-status.yaml (in-progress → review)

## Senior Developer Review (AI)

**Reviewer:** Code Review Agent  
**Date:** 2026-02-23  
**Outcome:** Changes Requested → Fixed → Approved  
**Issues Found:** 9 (3 High, 4 Medium, 2 Low)

### Critical Issues Fixed

1. **AC #6 Not Fully Implemented** (HIGH) - Error toast notification added in page.tsx useEffect
2. **Silent Polling Failures** (HIGH) - Polling failures now tracked and surfaced to user after 3 consecutive failures
3. **Race Condition** (HIGH) - Added `isPollingRef` to prevent overlapping poll requests

### Medium Issues Fixed

4. **Memory Leak** (MEDIUM) - Blob URL now properly managed with useRef and cleanup on unmount
5. **No Upload Progress** (MEDIUM) - Submit button now shows "Uploading..." with spinner during file upload
6. **No Retry Tracking** (MEDIUM) - Added `pollingFailures` state and `MAX_POLLING_FAILURES` constant
7. **Accessibility** (MEDIUM) - Added ARIA attributes to Progress component and error alerts

### Code Quality Improvements Applied

- Added `isPolling` and `pollingFailures` to hook return type
- Enhanced error messages for network failures
- Added visual indicator when connection is lost during translation
- Proper cleanup of intervals and blob URLs on component unmount

## Change Log

- 2026-02-23: Story created - ready for development
- 2026-02-23: Implementation complete - all 6 tasks completed, build successful, ready for review
- 2026-02-23: Code review complete - 9 issues identified and fixed, all HIGH/MEDIUM issues resolved
