feat: Implement Database Service and ViewModels for Messages and Support Requests
- 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.
This commit is contained in:
294
ARCHITECTURE.md
Normal file
294
ARCHITECTURE.md
Normal file
@@ -0,0 +1,294 @@
|
||||
# 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é
|
||||
Reference in New Issue
Block a user