# Architecture de TravelMate Admin ## 🏗️ Pattern MVVM (Model-View-ViewModel) Cette application utilise strictement le pattern MVVM avec CommunityToolkit.Mvvm pour une séparation claire des responsabilités. ``` ┌─────────────────────────────────────────────────────────┐ │ VIEW │ │ (XAML + Code-behind) │ │ DashboardPage │ MessagesPage │ SupportPage │ └─────────────┬───────────────────────────────────────────┘ │ Data Binding ▼ ┌─────────────────────────────────────────────────────────┐ │ VIEWMODEL │ │ (Business Logic + State) │ │ DashboardVM │ MessagesVM │ SupportVM │ └─────────────┬───────────────────────────────────────────┘ │ Calls ▼ ┌─────────────────────────────────────────────────────────┐ │ SERVICE │ │ (Data Access Layer) │ │ DatabaseService │ └─────────────┬───────────────────────────────────────────┘ │ SQL Queries ▼ ┌─────────────────────────────────────────────────────────┐ │ DATABASE │ │ MariaDB / MySQL │ │ messages │ support_requests │ └─────────────────────────────────────────────────────────┘ ``` ## 📂 Structure des Dossiers ### `/Models` **Responsabilité** : Représentation des données métier - `Message.cs` : Représente un message de demande - `SupportRequest.cs` : Représente une demande support **Caractéristiques** : - POCOs (Plain Old CLR Objects) - Propriétés avec getters/setters - Propriétés calculées (FullName, StatusText, etc.) - Pas de logique métier ### `/Services` **Responsabilité** : Couche d'accès aux données - `IDatabaseService.cs` : Contrat du service - `DatabaseService.cs` : Implémentation avec MySqlConnector **Caractéristiques** : - Méthodes asynchrones (Task) - Gestion des connexions MySQL - Gestion des erreurs avec try/catch - Logs de débogage **Méthodes principales** : ```csharp Task> GetAllAsync() Task> GetFilteredAsync(bool? isDone) Task GetPendingCountAsync() Task GetDoneCountAsync() Task UpdateStatusAsync(int id, bool done) Task TestConnectionAsync() ``` ### `/ViewModels` **Responsabilité** : Logique de présentation et état de l'UI - `DashboardViewModel.cs` : Gestion du dashboard - `MessagesViewModel.cs` : Gestion de la liste des messages - `SupportViewModel.cs` : Gestion des demandes support **Caractéristiques** : - Hérite de `ObservableObject` (CommunityToolkit.Mvvm) - Utilise `[ObservableProperty]` pour les propriétés bindables - Utilise `[RelayCommand]` pour les commandes - Injection de dépendance via constructeur **Exemple de propriété observable** : ```csharp [ObservableProperty] private bool isLoading; // Génère automatiquement IsLoading avec INotifyPropertyChanged ``` **Exemple de commande** : ```csharp [RelayCommand] public async Task LoadMessagesAsync() { // Logique de chargement } // Génère automatiquement LoadMessagesCommand : ICommand ``` ### `/Views` **Responsabilité** : Interface utilisateur - `DashboardPage.xaml/.cs` - `MessagesPage.xaml/.cs` - `SupportPage.xaml/.cs` **Caractéristiques** : - XAML pour la structure UI - Code-behind minimal (uniquement OnAppearing) - Data Binding vers le ViewModel - Converters pour la présentation ### `/Converters` **Responsabilité** : Conversion de données pour l'affichage - `BoolConverters.cs` : - `BoolToStatusTextConverter` : bool → "Marquer comme fait" - `BoolToColorConverter` : bool → Color ### `/Configuration` **Responsabilité** : Configuration de l'application - `AppSettings.cs` : Paramètres de connexion DB ## 🔄 Flux de Données ### 1. Chargement des Données ``` User Opens Page ↓ OnAppearing() appelé ↓ LoadCommand.Execute() ↓ ViewModel appelle Service ↓ Service exécute requête SQL ↓ Données retournées au ViewModel ↓ ViewModel met à jour ObservableCollection ↓ INotifyPropertyChanged déclenché ↓ UI se met à jour automatiquement ``` ### 2. Action Utilisateur (Changer statut) ``` User clique sur Button ↓ Command bindée exécutée ↓ ViewModel.ToggleStatusCommand ↓ Service.UpdateStatusAsync(id, !done) ↓ SQL UPDATE exécuté ↓ Success → ViewModel met à jour l'objet local ↓ INotifyPropertyChanged → UI refresh ``` ## 🧩 Injection de Dépendances Configuration dans `MauiProgram.cs` : ```csharp // Services (Singleton car un seul pour toute l'app) builder.Services.AddSingleton(); // ViewModels builder.Services.AddSingleton(); // Singleton = même instance builder.Services.AddTransient(); // Transient = nouvelle instance // Views builder.Services.AddSingleton(); builder.Services.AddTransient(); ``` **Pourquoi Singleton vs Transient ?** - **Singleton** : Dashboard (état partagé, chargé une fois) - **Transient** : Pages de liste (rafraîchies à chaque visite) ## 🎨 Navigation Gestion via `AppShell.xaml` : ```xaml ``` Navigation programmatique : ```csharp await Shell.Current.GoToAsync("//MessagesPage"); ``` ## 🔐 Sécurité **Actuellement** : - Mot de passe en clair dans AppSettings.cs **Pour la Production** : - Utiliser variables d'environnement - Chiffrer la chaîne de connexion - Utiliser Azure Key Vault ou équivalent - Implémenter authentification utilisateur - Logger les actions sensibles ## 📊 Performance **Optimisations actuelles** : - Connexions fermées automatiquement (using) - Requêtes asynchrones (async/await) - Filtres côté base de données (WHERE clause) - Tri côté base de données (ORDER BY) **Optimisations futures possibles** : - Pagination pour grandes listes - Mise en cache des données - Connection pooling (déjà géré par MySqlConnector) - Lazy loading ## 🧪 Testabilité Architecture testable grâce à : - Interface `IDatabaseService` (mockable) - ViewModels découplés des Views - Injection de dépendances - Logique métier dans ViewModels Exemple de test unitaire (potentiel) : ```csharp [Test] public async Task LoadMessages_ShouldPopulateCollection() { // Arrange var mockService = new Mock(); mockService.Setup(s => s.GetAllMessagesAsync()) .ReturnsAsync(new List { /* ... */ }); var vm = new MessagesViewModel(mockService.Object); // Act await vm.LoadMessagesCommand.ExecuteAsync(null); // Assert Assert.That(vm.Messages.Count, Is.GreaterThan(0)); } ``` ## 🚀 Extensibilité Pour ajouter une nouvelle entité : 1. **Model** : Créer `NewEntity.cs` 2. **Service** : Ajouter méthodes dans `IDatabaseService` et `DatabaseService` 3. **ViewModel** : Créer `NewEntityViewModel.cs` 4. **View** : Créer `NewEntityPage.xaml/.cs` 5. **DI** : Enregistrer dans `MauiProgram.cs` 6. **Navigation** : Ajouter dans `AppShell.xaml` ## 📝 Conventions de Code - **Naming** : - ViewModels : `*ViewModel.cs` - Pages : `*Page.xaml/.cs` - Services : `*Service.cs` avec interface `I*Service.cs` - **Async** : - Toujours utiliser `async/await` - Suffixe `Async` pour les méthodes - **MVVM** : - Pas de logique dans code-behind (sauf OnAppearing) - Tout passe par le ViewModel - Binding bidirectionnel quand nécessaire --- **Cette architecture garantit** : - ✅ Maintenabilité - ✅ Testabilité - ✅ Séparation des responsabilités - ✅ Réutilisabilité - ✅ Extensibilité