# Fonctionnalité : Ajustement Automatique du Prix

## Vue d'ensemble

Cette fonctionnalité implémente l'ajustement automatique du prix d'un rendez-vous lorsque la durée de la séance dépasse la durée prévue du service.

## Comportement

### Déclenchement

La vérification et la proposition d'ajustement du prix se déclenchent **automatiquement** lorsque :

1. Un service est sélectionné (avec `duration_minutes` et `base_price` définis)
2. L'utilisateur **modifie l'heure de début OU l'heure de fin**
3. La durée calculée de la séance (`end_time - start_time`) est **supérieure** à la durée du service

**Modification clé** : L'alerte se déclenche maintenant sur **toute modification de durée** (heure de début ou de fin), pas seulement sur la modification manuelle de l'heure de fin.

### Calcul du Prix Proposé

```javascript
ratio = duration_séance / duration_service
new_price = base_price × ratio
```

**Exemple :**
- Service : 60 minutes, 20 TND
- Séance : 90 minutes
- Ratio : 90 / 60 = 1.5
- Nouveau prix = 20 × 1.5 = 30 TND

### Interface Utilisateur

Lorsque les conditions sont remplies, une **alerte inline** (bandeau) s'affiche juste au-dessus du champ prix avec :

1. **Icône d'avertissement** (⚠️) avec couleur ambre
2. **Message principal** : Durée modifiée avec comparaison
3. **Question** : "Voulez-vous adapter le prix à X TND ?"
4. **Bloc de calcul** (fond ambre) :
   - Détail du calcul : `base_price × ratio = new_price`
5. **Deux boutons** :
   - ✓ **"Adapter le prix"** : Met à jour le champ `price_at_booking` avec le nouveau prix
   - ✗ **"Garder le prix actuel"** : Ferme l'alerte sans modification

### Avantages de l'Alerte Inline

✅ **Non-intrusive** : Pas de popup bloquante
✅ **Contextuelle** : Apparaît directement à côté du champ prix
✅ **Toujours visible** : L'utilisateur voit l'alerte et le champ prix en même temps
✅ **Responsive** : S'adapte à toutes les tailles d'écran
✅ **Peut être ignorée** : L'utilisateur peut continuer sans agir sur l'alerte

### Points Importants

#### 1. Le Prix Reste Toujours Modifiable
- Le champ `price_at_booking` est **toujours visible** et **modifiable manuellement**
- L'utilisateur peut ajuster le prix à tout moment, même après avoir accepté ou refusé une proposition

#### 2. Détection Automatique
- L'alerte se déclenche automatiquement dès que la durée calculée dépasse celle du service
- Fonctionne pour :
  - Modification de l'heure de début (qui recalcule l'heure de fin)
  - Modification de l'heure de fin
  - Changement de service

#### 3. Disparition Automatique
- L'alerte se masque automatiquement si la durée redevient normale (≤ durée du service)
- Se masque après acceptation ou refus

## Implémentation Technique

### Fichiers Modifiés

1. **`resources/views/provider/appointments/create.blade.php`**
   - Ajout de l'alerte inline HTML
   - Logique JavaScript complète

2. **`resources/views/provider/appointments/edit.blade.php`**
   - Même implémentation avec adaptation pour l'édition
   - Initialisation des données du service au chargement

### Variables Globales JavaScript

```javascript
serviceDurationMinutes    // Durée du service sélectionné (en minutes)
serviceBasePrice          // Prix de base du service
isCheckingPrice           // Flag pour éviter les boucles infinies
pendingNewPrice           // Prix calculé en attente de confirmation
endTimeManuallySet        // Flag si l'heure de fin a été définie
priceAlertAnswered        // Flag si l'utilisateur a répondu à l'alerte
allowSubmit               // Flag pour autoriser la soumission après réponse
```

### Fonctions Principales

#### `handleFormSubmit(event)`
- **Déclenchée par** : Soumission du formulaire (bouton submit ou touche Entrée)
- **Rôle** : Vérifier si une alerte de prix doit être affichée avant soumission
- **Action** : 
  - Si `duration_séance ≠ duration_service` ET alerte non répondue : **bloque la soumission** avec `preventDefault()`
  - Affiche l'alerte et attend la réponse de l'utilisateur
  - Soumet automatiquement après la réponse (accepter ou refuser)

#### `checkForPriceAdjustment()`
- **Déclenchée par** : 
  - Event listener sur `start_time` (change) → après un délai de 100ms
  - Event listener sur `end_time` (change) → immédiatement
- **Rôle** : Calcule la durée de la séance et vérifie si elle diffère de celle du service
- **Action** : Affiche ou masque l'alerte selon le résultat (augmentation OU réduction)

#### `showPriceAlert(newPrice, ratio, sessionDurationMinutes)`
- **Rôle** : Affiche l'alerte inline avec les informations de calcul
- **Paramètres** :
  - `newPrice` : Prix calculé
  - `ratio` : Ratio durée_séance / durée_service
  - `sessionDurationMinutes` : Durée de la séance
- **Animation** : Scroll automatique vers l'alerte pour attirer l'attention

#### `hidePriceAlert()`
- **Rôle** : Masque l'alerte et réinitialise l'état
- **Déclenchée par** :
  - Durée redevient normale
  - Acceptation de l'ajustement
  - Refus de l'ajustement
  - Changement de service

#### `acceptPriceAdjustment()`
- **Rôle** : Met à jour le champ `price_at_booking` avec le nouveau prix
- **Action** : 
  - Masque l'alerte après mise à jour
  - Marque l'alerte comme répondue
  - L'utilisateur doit cliquer sur le bouton de soumission

#### `rejectPriceAdjustment()`
- **Rôle** : Conserve le prix actuel
- **Action** : 
  - Masque l'alerte sans modification
  - Marque l'alerte comme répondue
  - L'utilisateur doit cliquer sur le bouton de soumission

### Structure de l'Alerte Inline

```html
<div id="priceAlert" class="hidden mb-3 bg-amber-50 border-l-4 border-amber-500...">
  <div class="flex items-start">
    <!-- Icône d'avertissement -->
    <div class="flex-shrink-0">
      <svg class="h-5 w-5 text-amber-500">...</svg>
    </div>
    
    <!-- Contenu -->
    <div class="ml-3 flex-1">
      <!-- Message -->
      <p>Durée modifiée : X min (au lieu de Y min)</p>
      
      <!-- Question -->
      <p>Voulez-vous adapter le prix à Z TND ?</p>
      
      <!-- Calcul -->
      <div class="font-mono bg-amber-100">
        A TND × B = C TND
      </div>
      
      <!-- Boutons -->
      <div class="flex gap-2">
        <button onclick="acceptPriceAdjustment()">✓ Adapter le prix</button>
        <button onclick="rejectPriceAdjustment()">✗ Garder le prix actuel</button>
      </div>
    </div>
  </div>
</div>
```

## Flux Utilisateur

### Flux Normal (avec interaction sur l'alerte)

```mermaid
graph TD
    A[Sélection du service] --> B[Prix = base_price]
    B --> C[Heure de fin calculée automatiquement]
    C --> D{Utilisateur modifie start/end time?}
    D -->|Non| E[Fin]
    D -->|Oui| F[Recalcul durée séance]
    F --> G{duration_séance ≠ duration_service?}
    G -->|Non| H[Masquer alerte]
    G -->|Oui| I[Calcul nouveau prix proportionnel]
    I --> J[Affichage alerte inline]
    J --> K{Action utilisateur}
    K -->|Adapter| L[Prix = nouveau prix + masquer alerte]
    K -->|Garder| M[Masquer alerte]
    K -->|Ignorer| N[Alerte reste visible]
    L --> E
    M --> E
    N --> E
    H --> E
```

### Flux avec Soumission Prématurée (Entrée pressée)

```mermaid
graph TD
    A[Utilisateur modifie start/end time] --> B{duration ≠ service?}
    B -->|Non| C[Soumission autorisée]
    B -->|Oui| D{Alerte déjà répondue?}
    D -->|Oui| C
    D -->|Non| E[Bloquer soumission avec preventDefault]
    E --> F[Afficher alerte inline]
    F --> G[Scroll vers alerte]
    G --> H{Utilisateur clique}
    H -->|Adapter| I[Mettre à jour prix + masquer alerte]
    H -->|Garder| J[Conserver prix + masquer alerte]
    I --> K[Utilisateur clique sur bouton submit]
    J --> K
    K --> L[Soumission autorisée]
```

## Backend

### Validation

Les contrôleurs (AppointmentController) reçoivent la valeur de `price_at_booking` **telle que définie par l'utilisateur**.

Aucun recalcul côté backend n'est effectué sans confirmation explicite.

### Règles de Validation Existantes

Les validations suivantes restent inchangées :
- `start_time` < `end_time`
- `service_id` existe
- `client_id` existe (si fourni)
- `price_at_booking` >= 0

## Tests Manuels Recommandés

### Scénario 1 : Augmentation de durée (heure de fin)
1. Sélectionner un service (ex: 60 min, 20 TND)
2. Heure de fin auto-calculée à 10:00 (si début à 09:00)
3. Modifier l'heure de fin à 10:30 → 90 minutes
4. **Alerte inline apparaît** : "Durée augmentée"
5. Cliquer "Adapter le prix"
6. Prix devient 30 TND (20 × 1.5)
7. Alerte disparaît

### Scénario 2 : Augmentation de durée (heure de début)
1. Sélectionner un service (ex: 60 min, 20 TND)
2. Heure début: 09:00, fin auto: 10:00
3. **Modifier l'heure de début à 08:00**
4. Heure de fin RESTE à 10:00 (ne se recalcule pas)
5. Durée devient 120 minutes (08:00 → 10:00)
6. **Alerte inline apparaît** : "Durée augmentée"
7. Prix proposé : 40 TND (20 × 2.0)
8. Cliquer "Adapter le prix"
9. Prix devient 40 TND

### Scénario 3 : Soumission avec Entrée (cas critique) ⚠️
1. Sélectionner un service (ex: 60 min, 20 TND)
2. Heure début: 09:00, fin auto: 10:00
3. Modifier l'heure de début à 08:00 (durée → 120 min)
4. **Appuyer immédiatement sur Entrée** (sans attendre l'alerte)
5. ✅ **Soumission est bloquée** avec `preventDefault()`
6. **Alerte inline s'affiche automatiquement**
7. Scroll automatique vers l'alerte
8. Utilisateur DOIT répondre (adapter ou garder)
9. Après la réponse → Alerte disparaît
10. Utilisateur clique sur le bouton "Créer le rendez-vous"
11. Formulaire se soumet normalement

### Scénario 4 : Refus de l'ajustement
1. Sélectionner un service (ex: 60 min, 20 TND)
2. Modifier pour avoir 90 minutes
3. Alerte apparaît
4. Cliquer "Garder le prix actuel"
5. Prix reste à 20 TND
6. Alerte disparaît

### Scénario 4 : Réduction de durée
1. Sélectionner un service (ex: 60 min, 20 TND)
2. Heure début: 09:00, fin auto: 10:00
3. Modifier l'heure de fin à 09:30 → 30 minutes
4. **Alerte inline apparaît** : "Durée réduite"
5. Prix proposé : 10 TND (20 × 0.5)
6. Cliquer "Adapter le prix"
7. Prix devient 10 TND
8. Alerte disparaît

### Scénario 5 : Retour à durée normale
1. Sélectionner un service (ex: 60 min, 20 TND)
2. Modifier pour avoir 90 minutes
3. Alerte apparaît
4. **Sans cliquer sur les boutons**, remettre la durée à 60 minutes
5. Alerte disparaît automatiquement

### Scénario 6 : Modification manuelle après ajustement
1. Accepter un ajustement de prix (30 TND)
2. Modifier manuellement le champ prix à 25 TND
3. Soumettre le formulaire
4. Vérifier que le prix soumis est 25 TND

## Notes de Développement

- **Compatibilité** : Fonctionne avec les navigateurs modernes (ES6+)
- **Dépendances** : Aucune bibliothèque externe requise
- **Accessibilité** : L'alerte est lisible et utilisable au clavier
- **Responsive** : L'alerte s'adapte aux différentes tailles d'écran
- **Performance** : Délai de 100ms pour éviter les vérifications trop fréquentes lors du changement d'heure de début

## Design

### Couleurs Utilisées
- **Fond** : `bg-amber-50` (ambre très clair)
- **Bordure gauche** : `border-amber-500` (ambre moyen) - 4px
- **Texte** : `text-amber-800` (ambre foncé)
- **Icône** : `text-amber-500` (ambre moyen)
- **Bouton adapter** : `bg-amber-600` hover `bg-amber-700`
- **Bouton garder** : `bg-gray-200` hover `bg-gray-300`

### Justification du Choix Ambre
L'ambre (amber) est idéal pour les avertissements qui ne sont pas critiques :
- Moins agressif que le rouge
- Plus visible que le bleu informatif
- Indique une action recommandée mais optionnelle

## Améliorations Futures Possibles

1. **Animation d'entrée** : Ajouter une transition slide-down lors de l'apparition
2. **Son discret** : Option pour jouer un son lors de l'apparition de l'alerte
3. **Préférences utilisateur** : Se souvenir si l'utilisateur accepte généralement les ajustements
4. **Historique** : Logger les acceptations/refus pour analyse
5. **Multi-devise** : Adapter le symbole monétaire dynamiquement
6. **Tooltip** : Ajouter des tooltips explicatifs sur le calcul

