- Added DatabaseService to handle database operations for messages and support requests. - Created IDatabaseService interface to define the contract for database operations. - Developed ViewModels for Dashboard, Messages, and Support pages to manage data and commands. - Implemented XAML views for Dashboard, Messages, and Support, including data binding and UI elements. - Created SQL script for setting up the database schema and inserting test data.
295 lines
8.9 KiB
Markdown
295 lines
8.9 KiB
Markdown
# 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<T>)
|
|
- Gestion des connexions MySQL
|
|
- Gestion des erreurs avec try/catch
|
|
- Logs de débogage
|
|
|
|
**Méthodes principales** :
|
|
```csharp
|
|
Task<List<T>> GetAllAsync()
|
|
Task<List<T>> GetFilteredAsync(bool? isDone)
|
|
Task<int> GetPendingCountAsync()
|
|
Task<int> GetDoneCountAsync()
|
|
Task<bool> UpdateStatusAsync(int id, bool done)
|
|
Task<bool> 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<IDatabaseService, DatabaseService>();
|
|
|
|
// ViewModels
|
|
builder.Services.AddSingleton<DashboardViewModel>(); // Singleton = même instance
|
|
builder.Services.AddTransient<MessagesViewModel>(); // Transient = nouvelle instance
|
|
|
|
// Views
|
|
builder.Services.AddSingleton<DashboardPage>();
|
|
builder.Services.AddTransient<MessagesPage>();
|
|
```
|
|
|
|
**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
|
|
<TabBar>
|
|
<ShellContent Title="Dashboard" Route="DashboardPage" ... />
|
|
<ShellContent Title="Messages" Route="MessagesPage" ... />
|
|
<ShellContent Title="Support" Route="SupportPage" ... />
|
|
</TabBar>
|
|
```
|
|
|
|
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<IDatabaseService>();
|
|
mockService.Setup(s => s.GetAllMessagesAsync())
|
|
.ReturnsAsync(new List<Message> { /* ... */ });
|
|
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é
|