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:
Van Leemput Dayron
2026-01-12 18:04:10 +01:00
parent 74586c20ba
commit f9690045ea
60 changed files with 4325 additions and 0 deletions

294
ARCHITECTURE.md Normal file
View 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é