# Guide de Migration : Notifications Mobile

## ❌ AVANT (Quasar Notify - Ugly)

```typescript
import { useQuasar } from 'quasar'
const $q = useQuasar()

// Toast simple
$q.notify({
  type: 'positive',
  message: 'Étape validée',
  icon: 'flag',
  position: 'top'
})

// ❌ MAUVAIS : Question dans une notification
$q.notify({
  message: `Supprimer "${stage.name}" ?`,
  icon: 'delete',
  color: 'negative',
  actions: [
    { label: 'Annuler', color: 'white' },
    { label: 'Supprimer', color: 'white', handler: () => deleteStage() }
  ]
})
```

---

## ✅ APRÈS (MobileToast + MobileDialog - Premium)

```typescript
import { useMobileToast } from '@/composables/useMobileToast'
import { useMobileDialog } from '@/composables/useMobileDialog'

const toast = useMobileToast()
const dialog = useMobileDialog()

// Toast simple
toast.success('Étape validée')

// ✅ BON : Dialog de confirmation séparé
const confirmed = await dialog.confirmDelete(stage.name)
if (confirmed) {
  await deleteStage()
  toast.success('Étape supprimée')
}
```

---

## 📖 API Reference

### MobileToast

#### Méthodes

```typescript
// Success (vert)
toast.success(message: string, options?: {
  title?: string
  icon?: string
  timeout?: number  // default: 3000ms
  progress?: boolean  // default: true
  action?: () => void
})

// Error (rouge)
toast.error(message: string, options?: {
  title?: string
  icon?: string
  timeout?: number  // default: 5000ms
  progress?: boolean
  action?: () => void
})

// Warning (jaune)
toast.warning(message: string, options?: {
  title?: string
  icon?: string
  timeout?: number  // default: 3000ms
  progress?: boolean
  action?: () => void
})

// Info (bleu)
toast.info(message: string, options?: {
  title?: string
  icon?: string
  timeout?: number  // default: 3000ms
  progress?: boolean
  action?: () => void
})

// Fermer tous les toasts
toast.clear()
```

#### Exemples

```typescript
// Simple
toast.success('Sauvegardé !')

// Avec titre
toast.error('Erreur de réseau', {
  title: 'Connexion perdue',
  icon: 'wifi_off',
  timeout: 5000
})

// Avec action
toast.warning('Nouvelle version disponible', {
  action: () => window.location.reload()
})
```

---

### MobileDialog

#### Méthodes

```typescript
// Confirmation générique
const confirmed = await dialog.confirm({
  title?: string
  message: string
  icon?: string
  type?: 'danger' | 'warning' | 'info' | 'success'
  confirmLabel?: string  // default: 'Confirmer'
  cancelLabel?: string   // default: 'Annuler'
})

// Alerte (sans bouton annuler)
const ok = await dialog.alert({
  title?: string
  message: string
  icon?: string
  type?: 'danger' | 'warning' | 'info' | 'success'
  confirmLabel?: string  // default: 'OK'
})

// Confirmation de suppression (raccourci)
const confirmed = await dialog.confirmDelete(itemName: string)

// Fermer le dialog actuel
dialog.close()
```

#### Exemples

```typescript
// Suppression
const confirmed = await dialog.confirmDelete(stage.name)
if (confirmed) {
  await deleteStage()
}

// Avertissement
const ok = await dialog.confirm({
  title: 'Attention',
  message: 'Vous avez des modifications non sauvegardées',
  type: 'warning',
  icon: 'warning',
  confirmLabel: 'Continuer',
  cancelLabel: 'Annuler'
})

// Alerte simple
await dialog.alert({
  title: 'Succès',
  message: 'Plan créé avec succès !',
  type: 'success',
  icon: 'check_circle'
})
```

---

## 🔄 Patterns de Migration

### Pattern 1 : Toast simple

```diff
- $q.notify({
-   type: 'positive',
-   message: 'Étape validée',
-   icon: 'flag'
- })
+ toast.success('Étape validée')
```

### Pattern 2 : Notification avec question → Dialog

```diff
- $q.notify({
-   message: `Supprimer "${stage.name}" ?`,
-   color: 'negative',
-   actions: [
-     { label: 'Annuler', color: 'white' },
-     { label: 'Supprimer', handler: () => deleteStage() }
-   ]
- })
+ const confirmed = await dialog.confirmDelete(stage.name)
+ if (confirmed) {
+   await deleteStage()
+   toast.success('Étape supprimée')
+ }
```

### Pattern 3 : Toast avec action

```diff
- $q.notify({
-   message: 'Plan mis à jour',
-   actions: [
-     { label: 'Voir', handler: () => router.push(...) }
-   ]
- })
+ toast.success('Plan mis à jour', {
+   action: () => router.push(...)
+ })
```

### Pattern 4 : Erreur réseau

```diff
- $q.notify({
-   type: 'negative',
-   message: 'Erreur de connexion',
-   timeout: 5000
- })
+ toast.error('Erreur de connexion', {
+   title: 'Réseau',
+   icon: 'wifi_off',
+   timeout: 5000
+ })
```

---

## 🎨 Design Features

### MobileToast
- ✅ Glassmorphism avec backdrop-filter
- ✅ Position en haut (safe-area-inset)
- ✅ Gradients premium (vert/rouge/jaune/bleu)
- ✅ Animation slide-in rebondissante
- ✅ Barre de progression
- ✅ Vibration au tap
- ✅ Max 3 toasts simultanés
- ✅ Swipe pour fermer (futur)

### MobileDialog
- ✅ Overlay avec backdrop-blur
- ✅ Bottom sheet style
- ✅ Glassmorphism
- ✅ Icon coloré selon type
- ✅ Animation scale + bounce
- ✅ Boutons gradients
- ✅ Vibration longue (20ms)
- ✅ Tap overlay pour fermer

---

## 📍 Fichiers à Migrer

### Priority HIGH
- `apps/web/src/modules/map/pages/MapPage.mobile.vue` (20+ notifications)

### Priority MEDIUM
- `apps/web/src/modules/planner/pages/PlanViewPage.vue`
- `apps/web/src/modules/planner/components/*.vue`

### Priority LOW
- Autres pages web (desktop peut garder Quasar)

---

## 🚀 Quick Start

```typescript
import { useMobileToast } from '@/composables/useMobileToast'
import { useMobileDialog } from '@/composables/useMobileDialog'

export default {
  setup() {
    const toast = useMobileToast()
    const dialog = useMobileDialog()

    async function handleDelete() {
      const confirmed = await dialog.confirmDelete('Mon Plan')
      if (confirmed) {
        try {
          await api.deletePlan()
          toast.success('Plan supprimé')
        } catch (error) {
          toast.error('Erreur lors de la suppression')
        }
      }
    }

    return { handleDelete }
  }
}
```

---

## 🎯 Règles d'Utilisation

### ✅ FAIRE
- Toasts pour feedback rapide (success, error, info)
- Dialogs pour confirmations importantes
- Messages courts (max 2 lignes)
- Actions simples dans toast (1 action max)
- Vibration pour feedback tactile

### ❌ NE PAS FAIRE
- Poser des questions dans un toast
- Mettre 2+ actions dans un toast
- Messages longs (utiliser dialog)
- Empiler 10+ toasts
- Bloquer l'interface avec des toasts

---

## 🔧 Notes Techniques

### Toast Rendering
- Utilise `h()` + `render()` de Vue 3
- Teleport vers `<body>`
- Instance VNode conservée pour destroy
- Max 3 toasts : FIFO queue

### Dialog Rendering
- Promise-based (async/await)
- 1 seul dialog actif
- Overlay avec backdrop-blur (8px)
- Close via overlay ou boutons
- Retourne `boolean` (confirm/cancel)

### Performance
- Pas de réactivité inutile (refs locaux)
- Destroy propre avec `render(null, container)`
- Animation GPU (transform + opacity)
- Vibration native (navigator.vibrate)

---

## 📝 TODO

- [ ] Swipe to dismiss sur toasts
- [ ] Bottom position option pour toasts
- [ ] Dark mode adaptatif
- [ ] Son de notification (opt-in)
- [ ] Persistance des toasts critiques
- [ ] Queue priority system
- [ ] Analytics tracking

