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:
54
.gitignore
vendored
Normal file
54
.gitignore
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio cache/options directory
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Rider
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# MAUI Specific
|
||||||
|
**/AppPackages/
|
||||||
|
**/BundleArtifacts/
|
||||||
|
**/Package.StoreAssociation.xml
|
||||||
|
|
||||||
|
# Configuration sensible - NE PAS COMMIT !
|
||||||
|
# Décommentez si vous voulez ignorer votre configuration locale
|
||||||
|
# **/Configuration/AppSettings.cs
|
||||||
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é
|
||||||
182
CHANGELOG.md
Normal file
182
CHANGELOG.md
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# 📅 Changelog - TravelMate Admin
|
||||||
|
|
||||||
|
Toutes les modifications notables de ce projet seront documentées dans ce fichier.
|
||||||
|
|
||||||
|
Le format est basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/),
|
||||||
|
et ce projet adhère à [Semantic Versioning](https://semver.org/lang/fr/).
|
||||||
|
|
||||||
|
## [1.0.0] - 2026-01-12
|
||||||
|
|
||||||
|
### ✨ Ajouté
|
||||||
|
|
||||||
|
#### Architecture & Structure
|
||||||
|
- Architecture MVVM complète avec CommunityToolkit.Mvvm
|
||||||
|
- Pattern strict avec séparation Models/Views/ViewModels/Services
|
||||||
|
- Injection de dépendances configurée dans MauiProgram.cs
|
||||||
|
- Navigation Shell avec TabBar
|
||||||
|
|
||||||
|
#### Models
|
||||||
|
- `Message.cs` : Modèle pour les messages de demande avec propriétés calculées
|
||||||
|
- `SupportRequest.cs` : Modèle pour les demandes support avec propriétés calculées
|
||||||
|
|
||||||
|
#### Services
|
||||||
|
- `IDatabaseService.cs` : Interface du service de base de données
|
||||||
|
- `DatabaseService.cs` : Implémentation complète avec MySqlConnector
|
||||||
|
- Connexion à MariaDB/MySQL
|
||||||
|
- Méthodes CRUD asynchrones
|
||||||
|
- Gestion des erreurs et logs
|
||||||
|
- Test de connexion
|
||||||
|
|
||||||
|
#### ViewModels
|
||||||
|
- `DashboardViewModel.cs` : Gestion du tableau de bord avec statistiques
|
||||||
|
- `MessagesViewModel.cs` : Gestion de la liste des messages avec filtres
|
||||||
|
- `SupportViewModel.cs` : Gestion des demandes support avec filtres
|
||||||
|
- Utilisation de `[ObservableProperty]` et `[RelayCommand]`
|
||||||
|
- Commandes asynchrones pour toutes les opérations
|
||||||
|
|
||||||
|
#### Views
|
||||||
|
- `DashboardPage.xaml/.cs` : Page principale avec cartes de statistiques
|
||||||
|
- `MessagesPage.xaml/.cs` : Liste des messages avec CollectionView
|
||||||
|
- `SupportPage.xaml/.cs` : Liste des demandes support
|
||||||
|
- Design moderne avec dark theme (#1a1a1a)
|
||||||
|
- Layout responsive
|
||||||
|
- Indicateurs de chargement
|
||||||
|
|
||||||
|
#### UI/UX
|
||||||
|
- Dark theme par défaut avec palette de couleurs cohérente
|
||||||
|
- Cartes avec ombres et coins arrondis
|
||||||
|
- Animations smooth pour les interactions
|
||||||
|
- Empty states pour listes vides
|
||||||
|
- Pull-to-refresh sur les listes
|
||||||
|
- Filtres dynamiques (Tout / À faire / Fait)
|
||||||
|
|
||||||
|
#### Converters
|
||||||
|
- `BoolToStatusTextConverter` : Conversion bool → texte bouton
|
||||||
|
- `BoolToColorConverter` : Conversion bool → couleur bouton
|
||||||
|
|
||||||
|
#### Configuration
|
||||||
|
- `AppSettings.cs` : Configuration centralisée de la connexion DB
|
||||||
|
- Paramètres modifiables (Server, Port, Database, User, Password)
|
||||||
|
|
||||||
|
#### Base de Données
|
||||||
|
- Script SQL `database_setup.sql` complet :
|
||||||
|
- Création de la base `travelmateadmin`
|
||||||
|
- Table `messages` avec 8 colonnes et index
|
||||||
|
- Table `support_requests` avec 8 colonnes et index
|
||||||
|
- 4 messages de test
|
||||||
|
- 4 demandes support de test
|
||||||
|
- Encodage UTF-8 (utf8mb4)
|
||||||
|
|
||||||
|
#### Fonctionnalités
|
||||||
|
- Dashboard avec statistiques en temps réel
|
||||||
|
- Filtrage des demandes (tout/à faire/fait)
|
||||||
|
- Changement de statut d'une demande (toggle done)
|
||||||
|
- Tri par date (plus récent en haut)
|
||||||
|
- Rafraîchissement manuel des données
|
||||||
|
- Navigation entre les sections
|
||||||
|
- Indicateur de connexion DB
|
||||||
|
|
||||||
|
#### Packages NuGet
|
||||||
|
- `CommunityToolkit.Mvvm` v8.3.2
|
||||||
|
- `MySqlConnector` v2.4.0
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
- `README.md` : Documentation complète du projet (sections détaillées)
|
||||||
|
- `QUICKSTART.md` : Guide de démarrage rapide (5 minutes)
|
||||||
|
- `CONFIGURATION.md` : Guide de configuration DB avec exemples
|
||||||
|
- `ARCHITECTURE.md` : Documentation architecture MVVM détaillée
|
||||||
|
- `COMMANDS.md` : Référence des commandes de développement
|
||||||
|
- `SQL_REFERENCE.md` : Référence complète des requêtes SQL
|
||||||
|
- `PROJECT_SUMMARY.md` : Résumé du projet et checklist
|
||||||
|
- `.gitignore` : Configuration Git adaptée .NET MAUI
|
||||||
|
|
||||||
|
#### DevOps
|
||||||
|
- Configuration csproj pour multi-plateforme (Mac/Win/Android/iOS)
|
||||||
|
- Build scripts pour toutes les plateformes
|
||||||
|
- Compilation vérifiée et réussie
|
||||||
|
|
||||||
|
### 🎯 Plateformes Supportées
|
||||||
|
- ✅ macOS (MacCatalyst) - net10.0-maccatalyst
|
||||||
|
- ✅ Windows - net10.0-windows10.0.19041.0
|
||||||
|
- ⚠️ Android - net10.0-android (non testé)
|
||||||
|
- ⚠️ iOS - net10.0-ios (non testé)
|
||||||
|
|
||||||
|
### 📊 Statistiques
|
||||||
|
- **Fichiers créés** : 35+
|
||||||
|
- **Lignes de code** : ~2000+ (C# + XAML)
|
||||||
|
- **Modèles** : 2
|
||||||
|
- **Services** : 1 (+ interface)
|
||||||
|
- **ViewModels** : 3
|
||||||
|
- **Views** : 3 (+ code-behind)
|
||||||
|
- **Documentation** : 8 fichiers MD
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [Unreleased] - Fonctionnalités Futures
|
||||||
|
|
||||||
|
### 🚀 Planifié pour v1.1.0
|
||||||
|
- [ ] Mode light/dark configurable
|
||||||
|
- [ ] Recherche/filtrage avancé
|
||||||
|
- [ ] Export de données (CSV, PDF)
|
||||||
|
- [ ] Pagination pour grandes listes
|
||||||
|
- [ ] Statistiques graphiques (charts)
|
||||||
|
|
||||||
|
### 🔮 Planifié pour v1.2.0
|
||||||
|
- [ ] Authentification utilisateur
|
||||||
|
- [ ] Gestion des permissions
|
||||||
|
- [ ] Historique des modifications
|
||||||
|
- [ ] Notifications push
|
||||||
|
- [ ] Multi-langue (i18n)
|
||||||
|
|
||||||
|
### 🧪 Planifié pour v1.3.0
|
||||||
|
- [ ] Tests unitaires (ViewModels)
|
||||||
|
- [ ] Tests d'intégration (Services)
|
||||||
|
- [ ] CI/CD avec GitHub Actions
|
||||||
|
- [ ] Couverture de code
|
||||||
|
|
||||||
|
### 🎨 Améliorations UI/UX
|
||||||
|
- [ ] Animations de transitions
|
||||||
|
- [ ] Thèmes personnalisables
|
||||||
|
- [ ] Accessibilité (screen readers)
|
||||||
|
- [ ] Raccourcis clavier
|
||||||
|
|
||||||
|
### 🔧 Améliorations Techniques
|
||||||
|
- [ ] Connection pooling optimisé
|
||||||
|
- [ ] Cache des données
|
||||||
|
- [ ] Offline mode
|
||||||
|
- [ ] Synchronisation automatique
|
||||||
|
- [ ] Logs structurés (Serilog)
|
||||||
|
|
||||||
|
### 🔐 Sécurité
|
||||||
|
- [ ] Chiffrement de la chaîne de connexion
|
||||||
|
- [ ] Variables d'environnement
|
||||||
|
- [ ] Azure Key Vault integration
|
||||||
|
- [ ] Audit trail
|
||||||
|
- [ ] Rate limiting
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Types de Changements
|
||||||
|
|
||||||
|
- `Added` ✨ : Nouvelles fonctionnalités
|
||||||
|
- `Changed` 🔄 : Modifications de fonctionnalités existantes
|
||||||
|
- `Deprecated` ⚠️ : Fonctionnalités bientôt supprimées
|
||||||
|
- `Removed` 🗑️ : Fonctionnalités supprimées
|
||||||
|
- `Fixed` 🐛 : Corrections de bugs
|
||||||
|
- `Security` 🔐 : Corrections de sécurité
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Format des Versions
|
||||||
|
|
||||||
|
```
|
||||||
|
[MAJOR.MINOR.PATCH] - YYYY-MM-DD
|
||||||
|
|
||||||
|
MAJOR : Changements incompatibles de l'API
|
||||||
|
MINOR : Nouvelles fonctionnalités rétrocompatibles
|
||||||
|
PATCH : Corrections de bugs rétrocompatibles
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note** : Ce fichier sera mis à jour à chaque release avec les changements apportés.
|
||||||
311
COMMANDS.md
Normal file
311
COMMANDS.md
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
# Commandes Utiles - TravelMate Admin
|
||||||
|
|
||||||
|
## 🔧 Développement
|
||||||
|
|
||||||
|
### Restaurer les packages
|
||||||
|
```bash
|
||||||
|
dotnet restore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build le projet
|
||||||
|
```bash
|
||||||
|
# MacCatalyst
|
||||||
|
dotnet build -f net10.0-maccatalyst
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
dotnet build -f net10.0-windows10.0.19041.0
|
||||||
|
|
||||||
|
# Android
|
||||||
|
dotnet build -f net10.0-android
|
||||||
|
|
||||||
|
# iOS
|
||||||
|
dotnet build -f net10.0-ios
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lancer l'application
|
||||||
|
```bash
|
||||||
|
# MacCatalyst
|
||||||
|
dotnet build -t:Run -f net10.0-maccatalyst
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
dotnet build -t:Run -f net10.0-windows10.0.19041.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nettoyer le projet
|
||||||
|
```bash
|
||||||
|
dotnet clean
|
||||||
|
rm -rf TravelMateAdmin/bin TravelMateAdmin/obj
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebuild complet
|
||||||
|
```bash
|
||||||
|
dotnet clean
|
||||||
|
dotnet restore
|
||||||
|
dotnet build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🗄️ Base de Données
|
||||||
|
|
||||||
|
### Créer la base de données
|
||||||
|
```bash
|
||||||
|
mysql -u root -p < database_setup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Se connecter à MySQL
|
||||||
|
```bash
|
||||||
|
mysql -u root -p travelmateadmin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Afficher les tables
|
||||||
|
```sql
|
||||||
|
USE travelmateadmin;
|
||||||
|
SHOW TABLES;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Voir les données
|
||||||
|
```sql
|
||||||
|
-- Tous les messages
|
||||||
|
SELECT * FROM messages ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Messages en attente
|
||||||
|
SELECT * FROM messages WHERE done = FALSE;
|
||||||
|
|
||||||
|
-- Statistiques
|
||||||
|
SELECT
|
||||||
|
COUNT(*) as total,
|
||||||
|
SUM(done = FALSE) as pending,
|
||||||
|
SUM(done = TRUE) as completed
|
||||||
|
FROM messages;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ajouter un message de test
|
||||||
|
```sql
|
||||||
|
INSERT INTO messages (nom, prenom, email, message, done, created_at)
|
||||||
|
VALUES ('Test', 'User', 'test@example.com', 'Ceci est un test', FALSE, NOW());
|
||||||
|
```
|
||||||
|
|
||||||
|
### Marquer tous les messages comme non traités
|
||||||
|
```sql
|
||||||
|
UPDATE messages SET done = FALSE;
|
||||||
|
UPDATE support_requests SET done = FALSE;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Réinitialiser les données
|
||||||
|
```bash
|
||||||
|
mysql -u root -p travelmateadmin < database_setup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup de la base
|
||||||
|
```bash
|
||||||
|
mysqldump -u root -p travelmateadmin > backup_$(date +%Y%m%d_%H%M%S).sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore depuis un backup
|
||||||
|
```bash
|
||||||
|
mysql -u root -p travelmateadmin < backup_20260112_143000.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 NuGet Packages
|
||||||
|
|
||||||
|
### Voir les packages installés
|
||||||
|
```bash
|
||||||
|
dotnet list TravelMateAdmin/TravelMateAdmin.csproj package
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mettre à jour un package
|
||||||
|
```bash
|
||||||
|
dotnet add TravelMateAdmin/TravelMateAdmin.csproj package CommunityToolkit.Mvvm
|
||||||
|
dotnet add TravelMateAdmin/TravelMateAdmin.csproj package MySqlConnector
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mettre à jour tous les packages
|
||||||
|
```bash
|
||||||
|
dotnet list TravelMateAdmin/TravelMateAdmin.csproj package --outdated
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐛 Debugging
|
||||||
|
|
||||||
|
### Voir les logs
|
||||||
|
Dans le terminal où vous avez lancé l'app, les logs apparaissent via :
|
||||||
|
```csharp
|
||||||
|
System.Diagnostics.Debug.WriteLine("Mon log");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests de connexion MySQL
|
||||||
|
```bash
|
||||||
|
# Tester si MySQL est accessible
|
||||||
|
nc -zv localhost 3306
|
||||||
|
|
||||||
|
# Voir les processus MySQL
|
||||||
|
ps aux | grep mysql
|
||||||
|
|
||||||
|
# Démarrer MySQL (Mac avec Homebrew)
|
||||||
|
brew services start mysql
|
||||||
|
|
||||||
|
# Démarrer MySQL (Linux)
|
||||||
|
sudo service mysql start
|
||||||
|
|
||||||
|
# Démarrer MySQL (MAMP)
|
||||||
|
# Utiliser l'interface MAMP
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📱 Plateforme Spécifique
|
||||||
|
|
||||||
|
### MacCatalyst - Voir les logs système
|
||||||
|
```bash
|
||||||
|
log stream --predicate 'processImagePath contains "TravelMateAdmin"' --level debug
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android - Voir les logs
|
||||||
|
```bash
|
||||||
|
adb logcat | grep TravelMateAdmin
|
||||||
|
```
|
||||||
|
|
||||||
|
### iOS Simulator - Voir les logs
|
||||||
|
```bash
|
||||||
|
xcrun simctl spawn booted log stream --level debug | grep TravelMateAdmin
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Code Analysis
|
||||||
|
|
||||||
|
### Format le code
|
||||||
|
```bash
|
||||||
|
dotnet format TravelMateAdmin/TravelMateAdmin.csproj
|
||||||
|
```
|
||||||
|
|
||||||
|
### Analyser le code
|
||||||
|
```bash
|
||||||
|
dotnet build /p:TreatWarningsAsErrors=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Statistiques du Projet
|
||||||
|
|
||||||
|
### Compter les lignes de code
|
||||||
|
```bash
|
||||||
|
find TravelMateAdmin -name "*.cs" -not -path "*/obj/*" -not -path "*/bin/*" | xargs wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
### Voir l'arborescence
|
||||||
|
```bash
|
||||||
|
tree -I 'bin|obj' TravelMateAdmin/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Taille du projet
|
||||||
|
```bash
|
||||||
|
du -sh TravelMateAdmin/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Publication
|
||||||
|
|
||||||
|
### Publish MacCatalyst
|
||||||
|
```bash
|
||||||
|
dotnet publish -f net10.0-maccatalyst -c Release -p:CreatePackage=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publish Windows
|
||||||
|
```bash
|
||||||
|
dotnet publish -f net10.0-windows10.0.19041.0 -c Release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Créer un package pour Mac App Store
|
||||||
|
```bash
|
||||||
|
dotnet publish -f net10.0-maccatalyst -c Release \
|
||||||
|
-p:RuntimeIdentifier=maccatalyst-arm64 \
|
||||||
|
-p:CreatePackage=true \
|
||||||
|
-p:CodesignKey="Apple Distribution: Your Name" \
|
||||||
|
-p:CodesignProvision="Your Provisioning Profile"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Tests (futur)
|
||||||
|
|
||||||
|
### Ajouter un projet de tests
|
||||||
|
```bash
|
||||||
|
dotnet new xunit -n TravelMateAdmin.Tests
|
||||||
|
dotnet sln add TravelMateAdmin.Tests/TravelMateAdmin.Tests.csproj
|
||||||
|
dotnet add TravelMateAdmin.Tests reference TravelMateAdmin/TravelMateAdmin.csproj
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lancer les tests
|
||||||
|
```bash
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Git
|
||||||
|
|
||||||
|
### Initialiser le repo
|
||||||
|
```bash
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit: TravelMate Admin MAUI app"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ignorer les fichiers de build
|
||||||
|
Le `.gitignore` est déjà configuré pour :
|
||||||
|
- bin/, obj/
|
||||||
|
- .vs/, .vscode/
|
||||||
|
- Configuration sensible
|
||||||
|
|
||||||
|
### Créer une branche
|
||||||
|
```bash
|
||||||
|
git checkout -b feature/nouvelle-fonctionnalite
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 Sécurité
|
||||||
|
|
||||||
|
### Chiffrer la configuration (exemple)
|
||||||
|
```bash
|
||||||
|
# Générer une clé
|
||||||
|
openssl rand -base64 32
|
||||||
|
|
||||||
|
# Chiffrer un fichier
|
||||||
|
openssl enc -aes-256-cbc -salt -in AppSettings.cs -out AppSettings.cs.enc
|
||||||
|
|
||||||
|
# Déchiffrer
|
||||||
|
openssl enc -d -aes-256-cbc -in AppSettings.cs.enc -out AppSettings.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Maintenance
|
||||||
|
|
||||||
|
### Vérifier les dépendances obsolètes
|
||||||
|
```bash
|
||||||
|
dotnet list package --outdated
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mettre à jour .NET
|
||||||
|
```bash
|
||||||
|
# Vérifier la version actuelle
|
||||||
|
dotnet --version
|
||||||
|
|
||||||
|
# Télécharger la dernière version
|
||||||
|
# https://dotnet.microsoft.com/download
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nettoyer NuGet cache
|
||||||
|
```bash
|
||||||
|
dotnet nuget locals all --clear
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Tips & Tricks
|
||||||
|
|
||||||
|
### Hot Reload
|
||||||
|
Lors du développement, les changements XAML sont appliqués en temps réel avec Hot Reload.
|
||||||
|
|
||||||
|
### Raccourcis Visual Studio
|
||||||
|
- `F5` : Run avec debug
|
||||||
|
- `Ctrl+F5` (Cmd+F5 Mac) : Run sans debug
|
||||||
|
- `Shift+F5` : Stop debugging
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
```bash
|
||||||
|
# Build en Release pour tester les performances réelles
|
||||||
|
dotnet build -c Release -f net10.0-maccatalyst
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multi-targeting
|
||||||
|
Pour cibler plusieurs plateformes en une fois :
|
||||||
|
```bash
|
||||||
|
dotnet build
|
||||||
|
# Build toutes les plateformes définies dans TargetFrameworks
|
||||||
|
```
|
||||||
102
CONFIGURATION.md
Normal file
102
CONFIGURATION.md
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
# Configuration de l'Application TravelMate Admin
|
||||||
|
|
||||||
|
## Configuration de Base de Données
|
||||||
|
|
||||||
|
Pour configurer la connexion à votre base de données, modifiez le fichier :
|
||||||
|
`TravelMateAdmin/Configuration/AppSettings.cs`
|
||||||
|
|
||||||
|
### Exemple pour une connexion locale :
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public const string Server = "localhost";
|
||||||
|
public const string Port = "3306";
|
||||||
|
public const string Database = "travelmateadmin";
|
||||||
|
public const string User = "root";
|
||||||
|
public const string Password = "monmotdepasse";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exemple pour une connexion distante :
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public const string Server = "192.168.1.100"; // IP du serveur
|
||||||
|
public const string Port = "3306";
|
||||||
|
public const string Database = "travelmateadmin";
|
||||||
|
public const string User = "admin";
|
||||||
|
public const string Password = "motdepassesecurise";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exemple avec un serveur cloud (ex: AWS RDS, Azure Database) :
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public const string Server = "myserver.mysql.database.azure.com";
|
||||||
|
public const string Port = "3306";
|
||||||
|
public const string Database = "travelmateadmin";
|
||||||
|
public const string User = "myadmin@myserver";
|
||||||
|
public const string Password = "P@ssw0rd!";
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
⚠️ **Important** : Ne commitez JAMAIS vos mots de passe dans Git !
|
||||||
|
|
||||||
|
Pour une meilleure sécurité en production :
|
||||||
|
|
||||||
|
1. Utilisez des variables d'environnement
|
||||||
|
2. Utilisez un système de gestion des secrets (Azure Key Vault, AWS Secrets Manager)
|
||||||
|
3. Chiffrez la chaîne de connexion
|
||||||
|
|
||||||
|
### Exemple avec variables d'environnement :
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public static string GetConnectionString()
|
||||||
|
{
|
||||||
|
var server = Environment.GetEnvironmentVariable("DB_SERVER") ?? Server;
|
||||||
|
var port = Environment.GetEnvironmentVariable("DB_PORT") ?? Port;
|
||||||
|
var database = Environment.GetEnvironmentVariable("DB_NAME") ?? Database;
|
||||||
|
var user = Environment.GetEnvironmentVariable("DB_USER") ?? User;
|
||||||
|
var password = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? Password;
|
||||||
|
|
||||||
|
return $"Server={server};Port={port};Database={database};User={user};Password={password};";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Paramètres Supplémentaires MySQL
|
||||||
|
|
||||||
|
Vous pouvez ajouter des paramètres supplémentaires à la chaîne de connexion :
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public static string GetConnectionString()
|
||||||
|
{
|
||||||
|
return $"Server={Server};Port={Port};Database={Database};User={User};Password={Password};" +
|
||||||
|
"SslMode=Required;" + // Pour SSL/TLS
|
||||||
|
"AllowPublicKeyRetrieval=True;" + // Pour l'authentification
|
||||||
|
"ConnectionTimeout=30;" + // Timeout en secondes
|
||||||
|
"DefaultCommandTimeout=30;"; // Timeout des commandes
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test de Connexion
|
||||||
|
|
||||||
|
Pour tester votre connexion, lancez l'application et vérifiez :
|
||||||
|
1. Le dashboard doit afficher "✓ Connecté" en haut à droite
|
||||||
|
2. Les statistiques doivent se charger
|
||||||
|
3. Si "✗ Déconnecté", vérifiez vos paramètres et les logs de débogage
|
||||||
|
|
||||||
|
## Dépannage Connexion
|
||||||
|
|
||||||
|
### Erreur "Access denied"
|
||||||
|
- Vérifiez le nom d'utilisateur et le mot de passe
|
||||||
|
- Vérifiez que l'utilisateur a les droits sur la base de données :
|
||||||
|
```sql
|
||||||
|
GRANT ALL PRIVILEGES ON travelmateadmin.* TO 'user'@'localhost';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erreur "Cannot connect to server"
|
||||||
|
- Vérifiez que MySQL est démarré
|
||||||
|
- Vérifiez le serveur et le port
|
||||||
|
- Vérifiez les règles de firewall
|
||||||
|
|
||||||
|
### Erreur "Unknown database"
|
||||||
|
- Vérifiez que la base de données existe
|
||||||
|
- Exécutez le script `database_setup.sql`
|
||||||
232
INDEX.md
Normal file
232
INDEX.md
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
# 📚 Index de Documentation - TravelMate Admin
|
||||||
|
|
||||||
|
Guide complet pour naviguer dans la documentation du projet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Pour Commencer
|
||||||
|
|
||||||
|
**Nouveau sur le projet ? Commencez ici :**
|
||||||
|
|
||||||
|
1. 📖 [README.md](README.md) - **Lisez-moi d'abord** - Vue d'ensemble du projet
|
||||||
|
2. ⚡ [QUICKSTART.md](QUICKSTART.md) - Installation en 5 minutes
|
||||||
|
3. 🎉 Lancez l'application !
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 Documentation par Catégorie
|
||||||
|
|
||||||
|
### 🏗️ Architecture & Développement
|
||||||
|
|
||||||
|
| Fichier | Description | Quand le consulter |
|
||||||
|
|---------|-------------|-------------------|
|
||||||
|
| [ARCHITECTURE.md](ARCHITECTURE.md) | Architecture MVVM détaillée, flux de données, patterns | Comprendre la structure du code |
|
||||||
|
| [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md) | Résumé complet, fichiers créés, checklist | Vue d'ensemble technique |
|
||||||
|
| [CHANGELOG.md](CHANGELOG.md) | Historique des versions et modifications | Voir les changements apportés |
|
||||||
|
|
||||||
|
### ⚙️ Configuration & Installation
|
||||||
|
|
||||||
|
| Fichier | Description | Quand le consulter |
|
||||||
|
|---------|-------------|-------------------|
|
||||||
|
| [QUICKSTART.md](QUICKSTART.md) | Guide rapide d'installation (5 min) | Première installation |
|
||||||
|
| [CONFIGURATION.md](CONFIGURATION.md) | Configuration de la base de données | Problèmes de connexion DB |
|
||||||
|
| [README.md](README.md) | Guide complet avec tous les détails | Documentation générale |
|
||||||
|
|
||||||
|
### 💻 Développement & Maintenance
|
||||||
|
|
||||||
|
| Fichier | Description | Quand le consulter |
|
||||||
|
|---------|-------------|-------------------|
|
||||||
|
| [COMMANDS.md](COMMANDS.md) | Commandes utiles (build, DB, debug) | Tâches de développement |
|
||||||
|
| [SQL_REFERENCE.md](SQL_REFERENCE.md) | Requêtes SQL complètes | Gérer la base de données |
|
||||||
|
|
||||||
|
### 📊 Base de Données
|
||||||
|
|
||||||
|
| Fichier | Description | Quand le consulter |
|
||||||
|
|---------|-------------|-------------------|
|
||||||
|
| [database_setup.sql](database_setup.sql) | Script SQL de création + données test | Initialiser la DB |
|
||||||
|
| [SQL_REFERENCE.md](SQL_REFERENCE.md) | Guide complet des requêtes SQL | Opérations sur les données |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Guides par Scénario
|
||||||
|
|
||||||
|
### Scénario 1 : Je veux installer l'app rapidement
|
||||||
|
1. [QUICKSTART.md](QUICKSTART.md) - Suivez les 5 étapes
|
||||||
|
2. [database_setup.sql](database_setup.sql) - Exécutez ce script
|
||||||
|
3. Modifiez `TravelMateAdmin/Configuration/AppSettings.cs`
|
||||||
|
4. Lancez l'app !
|
||||||
|
|
||||||
|
### Scénario 2 : J'ai des problèmes de connexion DB
|
||||||
|
1. [CONFIGURATION.md](CONFIGURATION.md) - Guide de dépannage
|
||||||
|
2. Vérifiez `AppSettings.cs`
|
||||||
|
3. [COMMANDS.md](COMMANDS.md) - Commandes de test MySQL
|
||||||
|
|
||||||
|
### Scénario 3 : Je veux comprendre le code
|
||||||
|
1. [ARCHITECTURE.md](ARCHITECTURE.md) - Pattern MVVM expliqué
|
||||||
|
2. [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md) - Structure des fichiers
|
||||||
|
3. Lisez les commentaires dans le code source
|
||||||
|
|
||||||
|
### Scénario 4 : Je veux ajouter une fonctionnalité
|
||||||
|
1. [ARCHITECTURE.md](ARCHITECTURE.md) - Section "Extensibilité"
|
||||||
|
2. [COMMANDS.md](COMMANDS.md) - Commandes de build/test
|
||||||
|
3. Suivez le pattern existant (Models → Services → ViewModels → Views)
|
||||||
|
|
||||||
|
### Scénario 5 : Je veux gérer les données
|
||||||
|
1. [SQL_REFERENCE.md](SQL_REFERENCE.md) - Toutes les requêtes SQL
|
||||||
|
2. [COMMANDS.md](COMMANDS.md) - Section "Base de Données"
|
||||||
|
|
||||||
|
### Scénario 6 : Je veux personnaliser l'UI
|
||||||
|
1. [README.md](README.md) - Section "Personnalisation"
|
||||||
|
2. Modifiez les couleurs dans les fichiers XAML
|
||||||
|
3. Consultez les Views existantes comme exemples
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Structure de la Documentation
|
||||||
|
|
||||||
|
```
|
||||||
|
Documentation/
|
||||||
|
├── README.md ⭐ Point d'entrée principal
|
||||||
|
├── QUICKSTART.md 🚀 Installation rapide
|
||||||
|
├── ARCHITECTURE.md 🏗️ Architecture technique
|
||||||
|
├── CONFIGURATION.md ⚙️ Configuration DB
|
||||||
|
├── COMMANDS.md 💻 Commandes de dev
|
||||||
|
├── SQL_REFERENCE.md 📊 Référence SQL
|
||||||
|
├── PROJECT_SUMMARY.md 📝 Résumé complet
|
||||||
|
├── CHANGELOG.md 📅 Historique des versions
|
||||||
|
└── INDEX.md 📚 Ce fichier
|
||||||
|
|
||||||
|
Code Source/
|
||||||
|
├── TravelMateAdmin/
|
||||||
|
│ ├── Models/ 📦 Modèles de données
|
||||||
|
│ ├── Services/ 🔧 Couche d'accès aux données
|
||||||
|
│ ├── ViewModels/ 🎭 Logique de présentation
|
||||||
|
│ ├── Views/ 🎨 Interface utilisateur
|
||||||
|
│ ├── Converters/ 🔄 Converters XAML
|
||||||
|
│ └── Configuration/ ⚙️ Configuration app
|
||||||
|
|
||||||
|
Base de Données/
|
||||||
|
└── database_setup.sql 🗄️ Script SQL
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Index par Mots-Clés
|
||||||
|
|
||||||
|
### A
|
||||||
|
- **Architecture MVVM** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
- **Ajouter une fonctionnalité** → [ARCHITECTURE.md](ARCHITECTURE.md#extensibilité)
|
||||||
|
|
||||||
|
### B
|
||||||
|
- **Base de données** → [CONFIGURATION.md](CONFIGURATION.md), [SQL_REFERENCE.md](SQL_REFERENCE.md)
|
||||||
|
- **Build** → [COMMANDS.md](COMMANDS.md#développement)
|
||||||
|
- **Backup** → [COMMANDS.md](COMMANDS.md#base-de-données)
|
||||||
|
|
||||||
|
### C
|
||||||
|
- **Commandes** → [COMMANDS.md](COMMANDS.md)
|
||||||
|
- **Configuration** → [CONFIGURATION.md](CONFIGURATION.md)
|
||||||
|
- **Connexion DB** → [CONFIGURATION.md](CONFIGURATION.md)
|
||||||
|
- **CommunityToolkit.Mvvm** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
|
||||||
|
### D
|
||||||
|
- **Dashboard** → [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md)
|
||||||
|
- **DatabaseService** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
- **Dépannage** → [CONFIGURATION.md](CONFIGURATION.md), [QUICKSTART.md](QUICKSTART.md)
|
||||||
|
|
||||||
|
### F
|
||||||
|
- **Filtres** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
|
||||||
|
### I
|
||||||
|
- **Installation** → [QUICKSTART.md](QUICKSTART.md)
|
||||||
|
- **Injection de dépendances** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
|
||||||
|
### M
|
||||||
|
- **MariaDB** → [CONFIGURATION.md](CONFIGURATION.md)
|
||||||
|
- **Messages** → [README.md](README.md)
|
||||||
|
- **MySQL** → [CONFIGURATION.md](CONFIGURATION.md), [SQL_REFERENCE.md](SQL_REFERENCE.md)
|
||||||
|
- **MVVM** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
|
||||||
|
### N
|
||||||
|
- **Navigation** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
- **NuGet** → [COMMANDS.md](COMMANDS.md)
|
||||||
|
|
||||||
|
### P
|
||||||
|
- **Performance** → [ARCHITECTURE.md](ARCHITECTURE.md), [SQL_REFERENCE.md](SQL_REFERENCE.md)
|
||||||
|
- **Problèmes** → [QUICKSTART.md](QUICKSTART.md), [CONFIGURATION.md](CONFIGURATION.md)
|
||||||
|
|
||||||
|
### Q
|
||||||
|
- **Quick Start** → [QUICKSTART.md](QUICKSTART.md)
|
||||||
|
|
||||||
|
### R
|
||||||
|
- **Requêtes SQL** → [SQL_REFERENCE.md](SQL_REFERENCE.md)
|
||||||
|
|
||||||
|
### S
|
||||||
|
- **Sécurité** → [CONFIGURATION.md](CONFIGURATION.md), [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
- **Services** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
- **SQL** → [SQL_REFERENCE.md](SQL_REFERENCE.md)
|
||||||
|
- **Support** → [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md)
|
||||||
|
|
||||||
|
### T
|
||||||
|
- **Tests** → [COMMANDS.md](COMMANDS.md), [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
|
||||||
|
### V
|
||||||
|
- **ViewModels** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
- **Views** → [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
|
||||||
|
### X
|
||||||
|
- **XAML** → [ARCHITECTURE.md](ARCHITECTURE.md), [README.md](README.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Statistiques de la Documentation
|
||||||
|
|
||||||
|
| Type | Nombre | Lignes Totales |
|
||||||
|
|------|--------|----------------|
|
||||||
|
| Fichiers Markdown | 8 | ~1500+ lignes |
|
||||||
|
| Sections | 100+ | - |
|
||||||
|
| Exemples de code | 50+ | - |
|
||||||
|
| Commandes | 100+ | - |
|
||||||
|
| Requêtes SQL | 60+ | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Aide Rapide
|
||||||
|
|
||||||
|
**Je ne trouve pas ce que je cherche !**
|
||||||
|
|
||||||
|
1. Utilisez Ctrl+F (Cmd+F sur Mac) dans ce fichier pour chercher un mot-clé
|
||||||
|
2. Consultez la section "Guides par Scénario" ci-dessus
|
||||||
|
3. Ouvrez [README.md](README.md) pour une vue d'ensemble
|
||||||
|
4. Tous les fichiers sont en Markdown, faciles à lire avec n'importe quel éditeur
|
||||||
|
|
||||||
|
**Suggestions de documentation manquante ?**
|
||||||
|
|
||||||
|
N'hésitez pas à créer une issue ou à contribuer !
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎓 Ordre de Lecture Recommandé
|
||||||
|
|
||||||
|
### Pour les Débutants
|
||||||
|
1. [README.md](README.md) - Vue d'ensemble
|
||||||
|
2. [QUICKSTART.md](QUICKSTART.md) - Installation
|
||||||
|
3. [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md) - Résumé
|
||||||
|
4. Lancez l'app et explorez !
|
||||||
|
|
||||||
|
### Pour les Développeurs
|
||||||
|
1. [ARCHITECTURE.md](ARCHITECTURE.md) - Comprendre la structure
|
||||||
|
2. [COMMANDS.md](COMMANDS.md) - Commandes de dev
|
||||||
|
3. [SQL_REFERENCE.md](SQL_REFERENCE.md) - Opérations DB
|
||||||
|
4. Code source dans TravelMateAdmin/
|
||||||
|
|
||||||
|
### Pour les Administrateurs DB
|
||||||
|
1. [CONFIGURATION.md](CONFIGURATION.md) - Configuration
|
||||||
|
2. [database_setup.sql](database_setup.sql) - Script d'installation
|
||||||
|
3. [SQL_REFERENCE.md](SQL_REFERENCE.md) - Référence complète
|
||||||
|
4. [COMMANDS.md](COMMANDS.md#base-de-données) - Maintenance
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Dernière mise à jour** : 12 janvier 2026
|
||||||
|
|
||||||
|
**Version de la documentation** : 1.0.0
|
||||||
233
PROJECT_SUMMARY.md
Normal file
233
PROJECT_SUMMARY.md
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
# ✅ PROJET COMPLÉTÉ - TravelMate Admin
|
||||||
|
|
||||||
|
## 📋 Résumé
|
||||||
|
|
||||||
|
Application desktop .NET MAUI (Mac/Windows) avec architecture MVVM pour gérer les demandes clients depuis une base de données MariaDB/MySQL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Ce qui a été créé
|
||||||
|
|
||||||
|
### 1. Structure MVVM Complète
|
||||||
|
|
||||||
|
#### **Models** (2 fichiers)
|
||||||
|
- ✅ `Message.cs` - Modèle pour les messages de demande
|
||||||
|
- ✅ `SupportRequest.cs` - Modèle pour les demandes support
|
||||||
|
|
||||||
|
#### **Services** (2 fichiers)
|
||||||
|
- ✅ `IDatabaseService.cs` - Interface du service de base de données
|
||||||
|
- ✅ `DatabaseService.cs` - Implémentation avec MySqlConnector
|
||||||
|
- Connexion à MariaDB/MySQL
|
||||||
|
- CRUD operations pour messages et support_requests
|
||||||
|
- Gestion asynchrone complète
|
||||||
|
|
||||||
|
#### **ViewModels** (3 fichiers)
|
||||||
|
- ✅ `DashboardViewModel.cs` - Gestion du tableau de bord
|
||||||
|
- ✅ `MessagesViewModel.cs` - Gestion de la liste des messages
|
||||||
|
- ✅ `SupportViewModel.cs` - Gestion des demandes support
|
||||||
|
- Tous utilisent CommunityToolkit.Mvvm (ObservableProperty, RelayCommand)
|
||||||
|
|
||||||
|
#### **Views** (3 paires XAML + Code-behind)
|
||||||
|
- ✅ `DashboardPage.xaml/.cs` - Tableau de bord avec statistiques
|
||||||
|
- ✅ `MessagesPage.xaml/.cs` - Liste des messages avec filtres
|
||||||
|
- ✅ `SupportPage.xaml/.cs` - Liste des demandes support
|
||||||
|
|
||||||
|
#### **Converters** (1 fichier)
|
||||||
|
- ✅ `BoolConverters.cs` - Conversion bool → texte et couleur pour les boutons
|
||||||
|
|
||||||
|
#### **Configuration** (1 fichier)
|
||||||
|
- ✅ `AppSettings.cs` - Configuration de la connexion DB
|
||||||
|
|
||||||
|
### 2. Configuration & Infrastructure
|
||||||
|
|
||||||
|
- ✅ `MauiProgram.cs` - Injection de dépendances configurée
|
||||||
|
- ✅ `AppShell.xaml` - Navigation Shell avec 3 onglets
|
||||||
|
- ✅ `TravelMateAdmin.csproj` - Packages NuGet ajoutés :
|
||||||
|
- CommunityToolkit.Mvvm (8.3.2)
|
||||||
|
- MySqlConnector (2.4.0)
|
||||||
|
|
||||||
|
### 3. Base de Données
|
||||||
|
|
||||||
|
- ✅ `database_setup.sql` - Script SQL complet :
|
||||||
|
- Création de la base `travelmateadmin`
|
||||||
|
- Table `messages` (8 colonnes)
|
||||||
|
- Table `support_requests` (8 colonnes)
|
||||||
|
- Données de test (4 messages + 4 demandes support)
|
||||||
|
|
||||||
|
### 4. Documentation
|
||||||
|
|
||||||
|
- ✅ `README.md` - Documentation complète du projet
|
||||||
|
- ✅ `QUICKSTART.md` - Guide de démarrage rapide (5 minutes)
|
||||||
|
- ✅ `CONFIGURATION.md` - Guide de configuration DB
|
||||||
|
- ✅ `ARCHITECTURE.md` - Documentation architecture MVVM
|
||||||
|
- ✅ `COMMANDS.md` - Commandes utiles pour le développement
|
||||||
|
- ✅ `.gitignore` - Fichiers à ignorer dans Git
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Fonctionnalités Implémentées
|
||||||
|
|
||||||
|
### ✅ Dashboard
|
||||||
|
- Affichage des statistiques en temps réel
|
||||||
|
- 4 cartes : Messages (en attente/traités) + Support (en attente/traités)
|
||||||
|
- Indicateur de statut de connexion
|
||||||
|
- Bouton de rafraîchissement
|
||||||
|
- Navigation vers les pages de détail
|
||||||
|
|
||||||
|
### ✅ Page Messages
|
||||||
|
- Liste complète des messages avec scroll
|
||||||
|
- Tri par date (plus récent en haut)
|
||||||
|
- Filtre : Tout / À faire / Fait
|
||||||
|
- Affichage : Nom, Prénom, Email, Message, Date, Statut
|
||||||
|
- Bouton pour changer le statut (fait ↔ en attente)
|
||||||
|
- Rafraîchissement manuel
|
||||||
|
|
||||||
|
### ✅ Page Support
|
||||||
|
- Liste des demandes support
|
||||||
|
- Même système de filtres que Messages
|
||||||
|
- Affichage : Nom, Prénom, Account Email, Contact Email, Message, Date, Statut
|
||||||
|
- Bouton pour changer le statut
|
||||||
|
- Rafraîchissement manuel
|
||||||
|
|
||||||
|
### ✅ Design
|
||||||
|
- **Dark theme** moderne et professionnel
|
||||||
|
- Couleurs configurables (Primary, Accent, Success, Warning)
|
||||||
|
- Cartes avec shadow et coins arrondis
|
||||||
|
- Layout responsive
|
||||||
|
- Indicateurs de chargement (ActivityIndicator)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Technologies Utilisées
|
||||||
|
|
||||||
|
| Technologie | Version | Usage |
|
||||||
|
|-------------|---------|-------|
|
||||||
|
| .NET | 10.0 | Framework principal |
|
||||||
|
| .NET MAUI | Dernière | UI multi-plateforme |
|
||||||
|
| CommunityToolkit.Mvvm | 8.3.2 | Pattern MVVM |
|
||||||
|
| MySqlConnector | 2.4.0 | Connexion MariaDB/MySQL |
|
||||||
|
| XAML | - | Interface utilisateur |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Structure du Projet
|
||||||
|
|
||||||
|
```
|
||||||
|
TravelMateAdmin/
|
||||||
|
├── TravelMateAdmin/ # Projet principal
|
||||||
|
│ ├── Configuration/
|
||||||
|
│ │ └── AppSettings.cs # Config DB
|
||||||
|
│ ├── Converters/
|
||||||
|
│ │ └── BoolConverters.cs # Converters XAML
|
||||||
|
│ ├── Models/
|
||||||
|
│ │ ├── Message.cs
|
||||||
|
│ │ └── SupportRequest.cs
|
||||||
|
│ ├── Services/
|
||||||
|
│ │ ├── IDatabaseService.cs
|
||||||
|
│ │ └── DatabaseService.cs
|
||||||
|
│ ├── ViewModels/
|
||||||
|
│ │ ├── DashboardViewModel.cs
|
||||||
|
│ │ ├── MessagesViewModel.cs
|
||||||
|
│ │ └── SupportViewModel.cs
|
||||||
|
│ ├── Views/
|
||||||
|
│ │ ├── DashboardPage.xaml/.cs
|
||||||
|
│ │ ├── MessagesPage.xaml/.cs
|
||||||
|
│ │ └── SupportPage.xaml/.cs
|
||||||
|
│ ├── App.xaml/.cs
|
||||||
|
│ ├── AppShell.xaml/.cs
|
||||||
|
│ ├── MauiProgram.cs
|
||||||
|
│ └── TravelMateAdmin.csproj
|
||||||
|
├── database_setup.sql # Script SQL
|
||||||
|
├── README.md # Documentation principale
|
||||||
|
├── QUICKSTART.md # Guide rapide
|
||||||
|
├── CONFIGURATION.md # Guide configuration
|
||||||
|
├── ARCHITECTURE.md # Documentation architecture
|
||||||
|
├── COMMANDS.md # Commandes utiles
|
||||||
|
└── .gitignore # Git ignore
|
||||||
|
|
||||||
|
Total: 35+ fichiers créés/modifiés
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 État du Projet
|
||||||
|
|
||||||
|
### ✅ Complété (100%)
|
||||||
|
|
||||||
|
- [x] Architecture MVVM complète
|
||||||
|
- [x] Modèles de données (Message, SupportRequest)
|
||||||
|
- [x] Service de base de données avec toutes les méthodes
|
||||||
|
- [x] ViewModels avec CommunityToolkit.Mvvm
|
||||||
|
- [x] Vues XAML avec design moderne
|
||||||
|
- [x] Converters pour l'affichage
|
||||||
|
- [x] Injection de dépendances
|
||||||
|
- [x] Navigation Shell
|
||||||
|
- [x] Script SQL avec données de test
|
||||||
|
- [x] Documentation complète
|
||||||
|
- [x] Compilation réussie ✅
|
||||||
|
|
||||||
|
### ⏭️ Étapes Suivantes (Optionnel)
|
||||||
|
|
||||||
|
- [ ] Ajouter authentification utilisateur
|
||||||
|
- [ ] Implémenter pagination pour grandes listes
|
||||||
|
- [ ] Ajouter recherche/filtrage avancé
|
||||||
|
- [ ] Exporter les données (CSV, PDF)
|
||||||
|
- [ ] Notifications push
|
||||||
|
- [ ] Tests unitaires
|
||||||
|
- [ ] Mode light/dark configurable
|
||||||
|
- [ ] Statistiques avancées (graphiques)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Pour Commencer
|
||||||
|
|
||||||
|
### Option 1 : Rapide (5 minutes)
|
||||||
|
```bash
|
||||||
|
# 1. Configurer la base de données
|
||||||
|
mysql -u root -p < database_setup.sql
|
||||||
|
|
||||||
|
# 2. Modifier AppSettings.cs avec vos identifiants MySQL
|
||||||
|
|
||||||
|
# 3. Lancer l'app
|
||||||
|
dotnet build -t:Run -f net10.0-maccatalyst # Mac
|
||||||
|
# OU
|
||||||
|
dotnet build -t:Run -f net10.0-windows10.0.19041.0 # Windows
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2 : Détaillée
|
||||||
|
Consultez `QUICKSTART.md` pour un guide pas-à-pas complet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎓 Points Clés de l'Architecture
|
||||||
|
|
||||||
|
1. **Séparation des responsabilités** : MVVM strict
|
||||||
|
2. **Réactivité** : INotifyPropertyChanged automatique
|
||||||
|
3. **Asynchrone** : Toutes les opérations DB sont async
|
||||||
|
4. **Injection de dépendances** : Services injectés automatiquement
|
||||||
|
5. **Testabilité** : Interface IDatabaseService mockable
|
||||||
|
6. **Extensibilité** : Facile d'ajouter de nouvelles entités
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Support
|
||||||
|
|
||||||
|
- **README.md** : Documentation générale
|
||||||
|
- **QUICKSTART.md** : Installation rapide
|
||||||
|
- **CONFIGURATION.md** : Problèmes de connexion DB
|
||||||
|
- **ARCHITECTURE.md** : Comprendre le code
|
||||||
|
- **COMMANDS.md** : Commandes de développement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎉 Félicitations !
|
||||||
|
|
||||||
|
Vous avez maintenant une application d'administration complète et professionnelle avec :
|
||||||
|
- ✅ Code propre et bien structuré
|
||||||
|
- ✅ Pattern MVVM moderne
|
||||||
|
- ✅ Interface utilisateur intuitive
|
||||||
|
- ✅ Base de données intégrée
|
||||||
|
- ✅ Documentation exhaustive
|
||||||
|
- ✅ Prête à être étendue
|
||||||
|
|
||||||
|
**Prochaine étape** : Lancez l'application et explorez les fonctionnalités ! 🚀
|
||||||
123
QUICKSTART.md
Normal file
123
QUICKSTART.md
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# 🚀 Guide de Démarrage Rapide - TravelMate Admin
|
||||||
|
|
||||||
|
## Installation en 5 Minutes
|
||||||
|
|
||||||
|
### Étape 1 : Prérequis ✅
|
||||||
|
|
||||||
|
Installez si nécessaire :
|
||||||
|
- [.NET 8+ SDK](https://dotnet.microsoft.com/download)
|
||||||
|
- [MySQL/MariaDB](https://dev.mysql.com/downloads/) ou [MAMP](https://www.mamp.info/) (Mac) / [XAMPP](https://www.apachefriends.org/) (Windows)
|
||||||
|
|
||||||
|
### Étape 2 : Base de Données 🗄️
|
||||||
|
|
||||||
|
**Option A - Avec MySQL en ligne de commande :**
|
||||||
|
```bash
|
||||||
|
mysql -u root -p < database_setup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B - Avec phpMyAdmin ou MySQL Workbench :**
|
||||||
|
1. Créez une base de données nommée `travelmateadmin`
|
||||||
|
2. Importez le fichier `database_setup.sql`
|
||||||
|
|
||||||
|
**Option C - Manuellement :**
|
||||||
|
```sql
|
||||||
|
CREATE DATABASE travelmateadmin;
|
||||||
|
USE travelmateadmin;
|
||||||
|
-- Puis copiez/collez le contenu de database_setup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3 : Configuration ⚙️
|
||||||
|
|
||||||
|
Ouvrez `TravelMateAdmin/Configuration/AppSettings.cs` et modifiez :
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public const string Server = "localhost"; // ✏️ Votre serveur
|
||||||
|
public const string Port = "3306"; // ✏️ Votre port
|
||||||
|
public const string Database = "travelmateadmin";
|
||||||
|
public const string User = "root"; // ✏️ Votre utilisateur
|
||||||
|
public const string Password = "VOTRE_MDP"; // ✏️ IMPORTANT: Changez ici !
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 4 : Restaurer les Packages 📦
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd TravelMateAdmin
|
||||||
|
dotnet restore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 5 : Lancer l'Application 🎉
|
||||||
|
|
||||||
|
**Sur Mac :**
|
||||||
|
```bash
|
||||||
|
dotnet build -t:Run -f net10.0-maccatalyst
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sur Windows :**
|
||||||
|
```bash
|
||||||
|
dotnet build -t:Run -f net10.0-windows10.0.19041.0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Avec Visual Studio :**
|
||||||
|
1. Ouvrez `TravelMateAdmin.sln`
|
||||||
|
2. Sélectionnez la plateforme (Mac Catalyst ou Windows)
|
||||||
|
3. Appuyez sur F5 ou cliquez sur ▶️ Run
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Vérification
|
||||||
|
|
||||||
|
Au lancement, vous devriez voir :
|
||||||
|
- ✅ Dashboard avec les statistiques
|
||||||
|
- ✅ "✓ Connecté" en haut à droite
|
||||||
|
- ✅ 4 messages et 4 demandes support (données de test)
|
||||||
|
|
||||||
|
## ❌ Problèmes ?
|
||||||
|
|
||||||
|
### "✗ Déconnecté" s'affiche
|
||||||
|
1. Vérifiez que MySQL est démarré
|
||||||
|
2. Vérifiez vos paramètres dans `AppSettings.cs`
|
||||||
|
3. Testez la connexion MySQL : `mysql -u root -p`
|
||||||
|
|
||||||
|
### Erreur "Cannot find project"
|
||||||
|
```bash
|
||||||
|
cd /Users/dayronvanleemput/Documents/Coding/TravelMateAdmin
|
||||||
|
dotnet restore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erreur de build
|
||||||
|
```bash
|
||||||
|
dotnet clean
|
||||||
|
dotnet restore
|
||||||
|
dotnet build
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Prochaines Étapes
|
||||||
|
|
||||||
|
1. **Tester l'application** : Naviguez entre Dashboard, Messages et Support
|
||||||
|
2. **Changer un statut** : Cliquez sur un bouton "Marquer comme fait"
|
||||||
|
3. **Filtrer** : Utilisez le menu déroulant pour filtrer les demandes
|
||||||
|
4. **Personnaliser** : Changez les couleurs dans les fichiers XAML
|
||||||
|
5. **Ajouter des données** : Ajoutez vos propres demandes dans la base
|
||||||
|
|
||||||
|
## 🎨 Captures d'Écran des Fonctionnalités
|
||||||
|
|
||||||
|
### Dashboard
|
||||||
|
- Vue d'ensemble des statistiques
|
||||||
|
- Cartes cliquables pour accéder aux détails
|
||||||
|
- Statut de connexion en temps réel
|
||||||
|
|
||||||
|
### Messages
|
||||||
|
- Liste complète des messages
|
||||||
|
- Filtre : Tout / À faire / Fait
|
||||||
|
- Action : Marquer comme fait/en attente
|
||||||
|
|
||||||
|
### Support
|
||||||
|
- Liste des demandes d'assistance
|
||||||
|
- Affichage des emails (compte et contact)
|
||||||
|
- Même système de filtres et actions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Besoin d'aide ?** Consultez le [README.md](README.md) complet ou le guide de [CONFIGURATION.md](CONFIGURATION.md)
|
||||||
433
SQL_REFERENCE.md
Normal file
433
SQL_REFERENCE.md
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
# 📊 SQL Queries Reference - TravelMate Admin
|
||||||
|
|
||||||
|
Requêtes SQL utiles pour gérer et interroger la base de données.
|
||||||
|
|
||||||
|
## 🔍 Requêtes de Consultation
|
||||||
|
|
||||||
|
### Messages
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Tous les messages
|
||||||
|
SELECT * FROM messages ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Messages en attente uniquement
|
||||||
|
SELECT * FROM messages WHERE done = FALSE ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Messages traités uniquement
|
||||||
|
SELECT * FROM messages WHERE done = TRUE ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Compter les messages par statut
|
||||||
|
SELECT
|
||||||
|
COUNT(*) AS total,
|
||||||
|
SUM(CASE WHEN done = FALSE THEN 1 ELSE 0 END) AS en_attente,
|
||||||
|
SUM(CASE WHEN done = TRUE THEN 1 ELSE 0 END) AS traites
|
||||||
|
FROM messages;
|
||||||
|
|
||||||
|
-- Messages récents (dernières 24h)
|
||||||
|
SELECT * FROM messages
|
||||||
|
WHERE created_at > NOW() - INTERVAL 24 HOUR
|
||||||
|
ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Messages d'un utilisateur spécifique
|
||||||
|
SELECT * FROM messages
|
||||||
|
WHERE email = 'jean.dupont@example.com'
|
||||||
|
ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Recherche dans les messages
|
||||||
|
SELECT * FROM messages
|
||||||
|
WHERE message LIKE '%RGPD%'
|
||||||
|
OR nom LIKE '%Dupont%'
|
||||||
|
ORDER BY created_at DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Support Requests
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Toutes les demandes support
|
||||||
|
SELECT * FROM support_requests ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Demandes en attente
|
||||||
|
SELECT * FROM support_requests WHERE done = FALSE ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Demandes traitées
|
||||||
|
SELECT * FROM support_requests WHERE done = TRUE ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Compter par statut
|
||||||
|
SELECT
|
||||||
|
COUNT(*) AS total,
|
||||||
|
SUM(CASE WHEN done = FALSE THEN 1 ELSE 0 END) AS en_attente,
|
||||||
|
SUM(CASE WHEN done = TRUE THEN 1 ELSE 0 END) AS traites
|
||||||
|
FROM support_requests;
|
||||||
|
|
||||||
|
-- Demandes d'un compte spécifique
|
||||||
|
SELECT * FROM support_requests
|
||||||
|
WHERE account_email = 'lucas.petit@example.com'
|
||||||
|
ORDER BY created_at DESC;
|
||||||
|
|
||||||
|
-- Recherche par email de contact
|
||||||
|
SELECT * FROM support_requests
|
||||||
|
WHERE contact_email = 'lucas.contact@example.com'
|
||||||
|
ORDER BY created_at DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Statistiques Globales
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Vue d'ensemble complète
|
||||||
|
SELECT
|
||||||
|
'Messages' AS type,
|
||||||
|
COUNT(*) AS total,
|
||||||
|
SUM(CASE WHEN done = FALSE THEN 1 ELSE 0 END) AS en_attente,
|
||||||
|
SUM(CASE WHEN done = TRUE THEN 1 ELSE 0 END) AS traites
|
||||||
|
FROM messages
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
'Support',
|
||||||
|
COUNT(*),
|
||||||
|
SUM(CASE WHEN done = FALSE THEN 1 ELSE 0 END),
|
||||||
|
SUM(CASE WHEN done = TRUE THEN 1 ELSE 0 END)
|
||||||
|
FROM support_requests;
|
||||||
|
|
||||||
|
-- Activité par jour (7 derniers jours)
|
||||||
|
SELECT
|
||||||
|
DATE(created_at) AS date,
|
||||||
|
COUNT(*) AS messages
|
||||||
|
FROM messages
|
||||||
|
WHERE created_at > NOW() - INTERVAL 7 DAY
|
||||||
|
GROUP BY DATE(created_at)
|
||||||
|
ORDER BY date DESC;
|
||||||
|
|
||||||
|
-- Volume par heure de la journée
|
||||||
|
SELECT
|
||||||
|
HOUR(created_at) AS heure,
|
||||||
|
COUNT(*) AS nombre_messages
|
||||||
|
FROM messages
|
||||||
|
GROUP BY HOUR(created_at)
|
||||||
|
ORDER BY heure;
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✏️ Requêtes de Modification
|
||||||
|
|
||||||
|
### Changer le Statut
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Marquer un message comme traité
|
||||||
|
UPDATE messages SET done = TRUE WHERE id = 1;
|
||||||
|
|
||||||
|
-- Marquer une demande support comme traitée
|
||||||
|
UPDATE support_requests SET done = TRUE WHERE id = 1;
|
||||||
|
|
||||||
|
-- Marquer comme non traité
|
||||||
|
UPDATE messages SET done = FALSE WHERE id = 1;
|
||||||
|
|
||||||
|
-- Marquer tous les messages en attente
|
||||||
|
UPDATE messages SET done = FALSE;
|
||||||
|
|
||||||
|
-- Marquer tous comme traités
|
||||||
|
UPDATE messages SET done = TRUE;
|
||||||
|
|
||||||
|
-- Marquer les vieux messages comme traités (plus de 30 jours)
|
||||||
|
UPDATE messages
|
||||||
|
SET done = TRUE
|
||||||
|
WHERE created_at < NOW() - INTERVAL 30 DAY AND done = FALSE;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ajouter des Données
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Nouveau message
|
||||||
|
INSERT INTO messages (nom, prenom, email, message, done, created_at)
|
||||||
|
VALUES (
|
||||||
|
'Nouveau',
|
||||||
|
'Test',
|
||||||
|
'test@example.com',
|
||||||
|
'Ceci est un nouveau message de test',
|
||||||
|
FALSE,
|
||||||
|
NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Nouvelle demande support
|
||||||
|
INSERT INTO support_requests (nom, prenom, account_email, contact_email, message, done, created_at)
|
||||||
|
VALUES (
|
||||||
|
'Support',
|
||||||
|
'Test',
|
||||||
|
'account@example.com',
|
||||||
|
'contact@example.com',
|
||||||
|
'Problème de connexion',
|
||||||
|
FALSE,
|
||||||
|
NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Ajouter plusieurs messages en une fois
|
||||||
|
INSERT INTO messages (nom, prenom, email, message, done, created_at) VALUES
|
||||||
|
('User1', 'Test', 'user1@test.com', 'Message 1', FALSE, NOW()),
|
||||||
|
('User2', 'Test', 'user2@test.com', 'Message 2', FALSE, NOW()),
|
||||||
|
('User3', 'Test', 'user3@test.com', 'Message 3', FALSE, NOW());
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supprimer des Données
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Supprimer un message spécifique
|
||||||
|
DELETE FROM messages WHERE id = 1;
|
||||||
|
|
||||||
|
-- Supprimer tous les messages traités
|
||||||
|
DELETE FROM messages WHERE done = TRUE;
|
||||||
|
|
||||||
|
-- Supprimer les vieux messages (plus de 90 jours)
|
||||||
|
DELETE FROM messages WHERE created_at < NOW() - INTERVAL 90 DAY;
|
||||||
|
|
||||||
|
-- Attention : Supprimer TOUTES les données
|
||||||
|
-- DELETE FROM messages;
|
||||||
|
-- DELETE FROM support_requests;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Maintenance
|
||||||
|
|
||||||
|
### Optimisation
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Analyser les tables
|
||||||
|
ANALYZE TABLE messages;
|
||||||
|
ANALYZE TABLE support_requests;
|
||||||
|
|
||||||
|
-- Optimiser les tables
|
||||||
|
OPTIMIZE TABLE messages;
|
||||||
|
OPTIMIZE TABLE support_requests;
|
||||||
|
|
||||||
|
-- Vérifier l'état de la table
|
||||||
|
CHECK TABLE messages;
|
||||||
|
CHECK TABLE support_requests;
|
||||||
|
|
||||||
|
-- Réparer une table (si nécessaire)
|
||||||
|
REPAIR TABLE messages;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Index
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Voir les index existants
|
||||||
|
SHOW INDEX FROM messages;
|
||||||
|
SHOW INDEX FROM support_requests;
|
||||||
|
|
||||||
|
-- Créer un index sur l'email (si performance lente)
|
||||||
|
CREATE INDEX idx_messages_email ON messages(email);
|
||||||
|
CREATE INDEX idx_support_account_email ON support_requests(account_email);
|
||||||
|
|
||||||
|
-- Supprimer un index
|
||||||
|
DROP INDEX idx_messages_email ON messages;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Exporter les données en SQL (en ligne de commande)
|
||||||
|
-- mysqldump -u root -p travelmateadmin > backup.sql
|
||||||
|
|
||||||
|
-- Exporter uniquement les messages
|
||||||
|
-- mysqldump -u root -p travelmateadmin messages > messages_backup.sql
|
||||||
|
|
||||||
|
-- Exporter sans données (structure seulement)
|
||||||
|
-- mysqldump -u root -p --no-data travelmateadmin > structure.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Rapports et Analytics
|
||||||
|
|
||||||
|
### Analyse des Messages
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Messages les plus fréquents par email
|
||||||
|
SELECT
|
||||||
|
email,
|
||||||
|
COUNT(*) AS nombre_messages,
|
||||||
|
MAX(created_at) AS dernier_message
|
||||||
|
FROM messages
|
||||||
|
GROUP BY email
|
||||||
|
ORDER BY nombre_messages DESC
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
-- Temps moyen de traitement
|
||||||
|
SELECT
|
||||||
|
AVG(TIMESTAMPDIFF(HOUR, created_at, NOW())) AS heures_moyennes
|
||||||
|
FROM messages
|
||||||
|
WHERE done = TRUE;
|
||||||
|
|
||||||
|
-- Messages par mois
|
||||||
|
SELECT
|
||||||
|
DATE_FORMAT(created_at, '%Y-%m') AS mois,
|
||||||
|
COUNT(*) AS nombre
|
||||||
|
FROM messages
|
||||||
|
GROUP BY DATE_FORMAT(created_at, '%Y-%m')
|
||||||
|
ORDER BY mois DESC;
|
||||||
|
|
||||||
|
-- Taux de complétion
|
||||||
|
SELECT
|
||||||
|
ROUND(SUM(done) / COUNT(*) * 100, 2) AS taux_completion_pourcent
|
||||||
|
FROM messages;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Analyse du Support
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Problèmes les plus fréquents (par mots-clés)
|
||||||
|
SELECT
|
||||||
|
CASE
|
||||||
|
WHEN message LIKE '%connexion%' THEN 'Connexion'
|
||||||
|
WHEN message LIKE '%mot de passe%' THEN 'Mot de passe'
|
||||||
|
WHEN message LIKE '%synchronisation%' THEN 'Synchronisation'
|
||||||
|
WHEN message LIKE '%facturation%' THEN 'Facturation'
|
||||||
|
ELSE 'Autre'
|
||||||
|
END AS categorie,
|
||||||
|
COUNT(*) AS nombre
|
||||||
|
FROM support_requests
|
||||||
|
GROUP BY categorie
|
||||||
|
ORDER BY nombre DESC;
|
||||||
|
|
||||||
|
-- Utilisateurs avec plusieurs demandes
|
||||||
|
SELECT
|
||||||
|
account_email,
|
||||||
|
COUNT(*) AS nombre_demandes,
|
||||||
|
SUM(done) AS traitees,
|
||||||
|
COUNT(*) - SUM(done) AS en_attente
|
||||||
|
FROM support_requests
|
||||||
|
GROUP BY account_email
|
||||||
|
HAVING nombre_demandes > 1
|
||||||
|
ORDER BY nombre_demandes DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Tests et Développement
|
||||||
|
|
||||||
|
### Générer des Données de Test
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Générer 50 messages aléatoires
|
||||||
|
INSERT INTO messages (nom, prenom, email, message, done, created_at)
|
||||||
|
SELECT
|
||||||
|
CONCAT('Nom', n.n),
|
||||||
|
CONCAT('Prenom', n.n),
|
||||||
|
CONCAT('test', n.n, '@example.com'),
|
||||||
|
CONCAT('Message de test numéro ', n.n),
|
||||||
|
n.n % 3 = 0, -- Un tiers sera "done"
|
||||||
|
NOW() - INTERVAL FLOOR(RAND() * 30) DAY
|
||||||
|
FROM (
|
||||||
|
SELECT @row := @row + 1 AS n
|
||||||
|
FROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) t1,
|
||||||
|
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) t2,
|
||||||
|
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) t3,
|
||||||
|
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) t4,
|
||||||
|
(SELECT @row := 0) r
|
||||||
|
LIMIT 50
|
||||||
|
) n;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Réinitialiser pour les Tests
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Vider toutes les tables
|
||||||
|
TRUNCATE TABLE messages;
|
||||||
|
TRUNCATE TABLE support_requests;
|
||||||
|
|
||||||
|
-- Réinitialiser les auto-increment
|
||||||
|
ALTER TABLE messages AUTO_INCREMENT = 1;
|
||||||
|
ALTER TABLE support_requests AUTO_INCREMENT = 1;
|
||||||
|
|
||||||
|
-- Recréer les données de test
|
||||||
|
SOURCE database_setup.sql;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 Sécurité et Utilisateurs
|
||||||
|
|
||||||
|
### Gestion des Utilisateurs
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Créer un utilisateur pour l'application
|
||||||
|
CREATE USER 'travelmateapp'@'localhost' IDENTIFIED BY 'votre_mot_de_passe';
|
||||||
|
|
||||||
|
-- Donner les permissions nécessaires
|
||||||
|
GRANT SELECT, INSERT, UPDATE ON travelmateadmin.* TO 'travelmateapp'@'localhost';
|
||||||
|
|
||||||
|
-- Ne PAS donner DELETE en production pour la sécurité
|
||||||
|
-- GRANT DELETE ON travelmateadmin.* TO 'travelmateapp'@'localhost';
|
||||||
|
|
||||||
|
-- Appliquer les changements
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
|
||||||
|
-- Voir les permissions d'un utilisateur
|
||||||
|
SHOW GRANTS FOR 'travelmateapp'@'localhost';
|
||||||
|
|
||||||
|
-- Révoquer une permission
|
||||||
|
REVOKE DELETE ON travelmateadmin.* FROM 'travelmateapp'@'localhost';
|
||||||
|
|
||||||
|
-- Supprimer un utilisateur
|
||||||
|
DROP USER 'travelmateapp'@'localhost';
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Informations sur la Base
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Voir toutes les bases de données
|
||||||
|
SHOW DATABASES;
|
||||||
|
|
||||||
|
-- Utiliser la base TravelMate
|
||||||
|
USE travelmateadmin;
|
||||||
|
|
||||||
|
-- Voir toutes les tables
|
||||||
|
SHOW TABLES;
|
||||||
|
|
||||||
|
-- Voir la structure d'une table
|
||||||
|
DESCRIBE messages;
|
||||||
|
DESCRIBE support_requests;
|
||||||
|
|
||||||
|
-- Voir le CREATE TABLE original
|
||||||
|
SHOW CREATE TABLE messages;
|
||||||
|
|
||||||
|
-- Taille de la base de données
|
||||||
|
SELECT
|
||||||
|
table_schema AS 'Database',
|
||||||
|
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'travelmateadmin';
|
||||||
|
|
||||||
|
-- Nombre de lignes par table
|
||||||
|
SELECT
|
||||||
|
TABLE_NAME,
|
||||||
|
TABLE_ROWS
|
||||||
|
FROM information_schema.TABLES
|
||||||
|
WHERE TABLE_SCHEMA = 'travelmateadmin';
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚨 Dépannage
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Vérifier les connexions actives
|
||||||
|
SHOW PROCESSLIST;
|
||||||
|
|
||||||
|
-- Tuer une connexion bloquée (remplacer X par l'ID)
|
||||||
|
-- KILL X;
|
||||||
|
|
||||||
|
-- Voir les variables MySQL
|
||||||
|
SHOW VARIABLES LIKE 'max_connections';
|
||||||
|
SHOW VARIABLES LIKE 'wait_timeout';
|
||||||
|
|
||||||
|
-- Voir le statut du serveur
|
||||||
|
SHOW STATUS;
|
||||||
|
|
||||||
|
-- Voir les erreurs récentes
|
||||||
|
SHOW WARNINGS;
|
||||||
|
SHOW ERRORS;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Tips
|
||||||
|
|
||||||
|
- Toujours tester vos requêtes DELETE/UPDATE avec SELECT d'abord
|
||||||
|
- Faites des backups avant toute modification importante
|
||||||
|
- Utilisez LIMIT dans vos requêtes de test
|
||||||
|
- Les index améliorent les performances SELECT mais ralentissent INSERT/UPDATE
|
||||||
|
- Utilisez EXPLAIN pour analyser les performances des requêtes
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Exemple d'analyse de performance
|
||||||
|
EXPLAIN SELECT * FROM messages WHERE done = FALSE ORDER BY created_at DESC;
|
||||||
|
```
|
||||||
34
TravelMateAdmin.sln
Normal file
34
TravelMateAdmin.sln
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.0.31903.59
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TravelMateAdmin", "TravelMateAdmin\TravelMateAdmin.csproj", "{760FF747-775F-4B67-A507-584C1D43D88E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{760FF747-775F-4B67-A507-584C1D43D88E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
14
TravelMateAdmin/App.xaml
Normal file
14
TravelMateAdmin/App.xaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version = "1.0" encoding = "UTF-8" ?>
|
||||||
|
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:local="clr-namespace:TravelMateAdmin"
|
||||||
|
x:Class="TravelMateAdmin.App">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
|
||||||
|
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
16
TravelMateAdmin/App.xaml.cs
Normal file
16
TravelMateAdmin/App.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Window CreateWindow(IActivationState? activationState)
|
||||||
|
{
|
||||||
|
return new Window(new AppShell());
|
||||||
|
}
|
||||||
|
}
|
||||||
44
TravelMateAdmin/AppShell.xaml
Normal file
44
TravelMateAdmin/AppShell.xaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Shell
|
||||||
|
x:Class="TravelMateAdmin.AppShell"
|
||||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:views="clr-namespace:TravelMateAdmin.Views"
|
||||||
|
Title="TravelMate Admin"
|
||||||
|
Shell.FlyoutBehavior="Flyout">
|
||||||
|
|
||||||
|
<Shell.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<Color x:Key="Primary">#1a1a1a</Color>
|
||||||
|
<Color x:Key="Accent">#5E50D9</Color>
|
||||||
|
<Style TargetType="TabBar" ApplyToDerivedTypes="True">
|
||||||
|
<Setter Property="Shell.TabBarBackgroundColor" Value="{StaticResource Primary}" />
|
||||||
|
<Setter Property="Shell.TabBarForegroundColor" Value="{StaticResource Accent}" />
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Shell.Resources>
|
||||||
|
|
||||||
|
<!-- Dashboard -->
|
||||||
|
<TabBar>
|
||||||
|
<ShellContent
|
||||||
|
Title="Dashboard"
|
||||||
|
Icon="home"
|
||||||
|
ContentTemplate="{DataTemplate views:DashboardPage}"
|
||||||
|
Route="DashboardPage" />
|
||||||
|
|
||||||
|
<!-- Messages -->
|
||||||
|
<ShellContent
|
||||||
|
Title="Messages"
|
||||||
|
Icon="mail"
|
||||||
|
ContentTemplate="{DataTemplate views:MessagesPage}"
|
||||||
|
Route="MessagesPage" />
|
||||||
|
|
||||||
|
<!-- Support -->
|
||||||
|
<ShellContent
|
||||||
|
Title="Support"
|
||||||
|
Icon="help"
|
||||||
|
ContentTemplate="{DataTemplate views:SupportPage}"
|
||||||
|
Route="SupportPage" />
|
||||||
|
</TabBar>
|
||||||
|
|
||||||
|
</Shell>
|
||||||
9
TravelMateAdmin/AppShell.xaml.cs
Normal file
9
TravelMateAdmin/AppShell.xaml.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
public partial class AppShell : Shell
|
||||||
|
{
|
||||||
|
public AppShell()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
17
TravelMateAdmin/Configuration/AppSettings.cs
Normal file
17
TravelMateAdmin/Configuration/AppSettings.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace TravelMateAdmin.Configuration;
|
||||||
|
|
||||||
|
public static class AppSettings
|
||||||
|
{
|
||||||
|
// Configuration de la base de données
|
||||||
|
// Modifiez ces valeurs selon votre environnement
|
||||||
|
public const string Server = "localhost";
|
||||||
|
public const string Port = "3306";
|
||||||
|
public const string Database = "travelmateadmin";
|
||||||
|
public const string User = "root";
|
||||||
|
public const string Password = "yourpassword";
|
||||||
|
|
||||||
|
public static string GetConnectionString()
|
||||||
|
{
|
||||||
|
return $"Server={Server};Port={Port};Database={Database};User={User};Password={Password};";
|
||||||
|
}
|
||||||
|
}
|
||||||
37
TravelMateAdmin/Converters/BoolConverters.cs
Normal file
37
TravelMateAdmin/Converters/BoolConverters.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.Converters;
|
||||||
|
|
||||||
|
public class BoolToStatusTextConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is bool isDone)
|
||||||
|
{
|
||||||
|
return isDone ? "Marquer en attente" : "Marquer comme fait";
|
||||||
|
}
|
||||||
|
return "Changer statut";
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoolToColorConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is bool isDone)
|
||||||
|
{
|
||||||
|
return isDone ? Color.FromArgb("#FFA726") : Color.FromArgb("#4CAF50");
|
||||||
|
}
|
||||||
|
return Color.FromArgb("#5E50D9");
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
36
TravelMateAdmin/MainPage.xaml
Normal file
36
TravelMateAdmin/MainPage.xaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="TravelMateAdmin.MainPage">
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
<VerticalStackLayout
|
||||||
|
Padding="30,0"
|
||||||
|
Spacing="25">
|
||||||
|
<Image
|
||||||
|
Source="dotnet_bot.png"
|
||||||
|
HeightRequest="185"
|
||||||
|
Aspect="AspectFit"
|
||||||
|
SemanticProperties.Description="dot net bot in a submarine number ten" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
Text="Hello, World!"
|
||||||
|
Style="{StaticResource Headline}"
|
||||||
|
SemanticProperties.HeadingLevel="Level1" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
Text="Welcome to .NET Multi-platform App UI"
|
||||||
|
Style="{StaticResource SubHeadline}"
|
||||||
|
SemanticProperties.HeadingLevel="Level2"
|
||||||
|
SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
x:Name="CounterBtn"
|
||||||
|
Text="Click me"
|
||||||
|
SemanticProperties.Hint="Counts the number of times you click"
|
||||||
|
Clicked="OnCounterClicked"
|
||||||
|
HorizontalOptions="Fill" />
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</ContentPage>
|
||||||
23
TravelMateAdmin/MainPage.xaml.cs
Normal file
23
TravelMateAdmin/MainPage.xaml.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
public partial class MainPage : ContentPage
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
public MainPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCounterClicked(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (count == 1)
|
||||||
|
CounterBtn.Text = $"Clicked {count} time";
|
||||||
|
else
|
||||||
|
CounterBtn.Text = $"Clicked {count} times";
|
||||||
|
|
||||||
|
SemanticScreenReader.Announce(CounterBtn.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
TravelMateAdmin/MauiProgram.cs
Normal file
40
TravelMateAdmin/MauiProgram.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using TravelMateAdmin.Services;
|
||||||
|
using TravelMateAdmin.ViewModels;
|
||||||
|
using TravelMateAdmin.Views;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
public static class MauiProgram
|
||||||
|
{
|
||||||
|
public static MauiApp CreateMauiApp()
|
||||||
|
{
|
||||||
|
var builder = MauiApp.CreateBuilder();
|
||||||
|
builder
|
||||||
|
.UseMauiApp<App>()
|
||||||
|
.ConfigureFonts(fonts =>
|
||||||
|
{
|
||||||
|
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||||
|
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
|
||||||
|
});
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
builder.Logging.AddDebug();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Register Services
|
||||||
|
builder.Services.AddSingleton<IDatabaseService, DatabaseService>();
|
||||||
|
|
||||||
|
// Register ViewModels
|
||||||
|
builder.Services.AddSingleton<DashboardViewModel>();
|
||||||
|
builder.Services.AddTransient<MessagesViewModel>();
|
||||||
|
builder.Services.AddTransient<SupportViewModel>();
|
||||||
|
|
||||||
|
// Register Views
|
||||||
|
builder.Services.AddSingleton<DashboardPage>();
|
||||||
|
builder.Services.AddTransient<MessagesPage>();
|
||||||
|
builder.Services.AddTransient<SupportPage>();
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
TravelMateAdmin/Models/Message.cs
Normal file
16
TravelMateAdmin/Models/Message.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace TravelMateAdmin.Models;
|
||||||
|
|
||||||
|
public class Message
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nom { get; set; } = string.Empty;
|
||||||
|
public string Prenom { get; set; } = string.Empty;
|
||||||
|
public string Email { get; set; } = string.Empty;
|
||||||
|
public string MessageText { get; set; } = string.Empty;
|
||||||
|
public bool Done { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public string FullName => $"{Prenom} {Nom}";
|
||||||
|
public string StatusText => Done ? "Traité" : "En attente";
|
||||||
|
public string CreatedAtFormatted => CreatedAt.ToString("dd/MM/yyyy HH:mm");
|
||||||
|
}
|
||||||
17
TravelMateAdmin/Models/SupportRequest.cs
Normal file
17
TravelMateAdmin/Models/SupportRequest.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace TravelMateAdmin.Models;
|
||||||
|
|
||||||
|
public class SupportRequest
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nom { get; set; } = string.Empty;
|
||||||
|
public string Prenom { get; set; } = string.Empty;
|
||||||
|
public string AccountEmail { get; set; } = string.Empty;
|
||||||
|
public string ContactEmail { get; set; } = string.Empty;
|
||||||
|
public string MessageText { get; set; } = string.Empty;
|
||||||
|
public bool Done { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public string FullName => $"{Prenom} {Nom}";
|
||||||
|
public string StatusText => Done ? "Traité" : "En attente";
|
||||||
|
public string CreatedAtFormatted => CreatedAt.ToString("dd/MM/yyyy HH:mm");
|
||||||
|
}
|
||||||
6
TravelMateAdmin/Platforms/Android/AndroidManifest.xml
Normal file
6
TravelMateAdmin/Platforms/Android/AndroidManifest.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
</manifest>
|
||||||
10
TravelMateAdmin/Platforms/Android/MainActivity.cs
Normal file
10
TravelMateAdmin/Platforms/Android/MainActivity.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.Content.PM;
|
||||||
|
using Android.OS;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
|
||||||
|
public class MainActivity : MauiAppCompatActivity
|
||||||
|
{
|
||||||
|
}
|
||||||
15
TravelMateAdmin/Platforms/Android/MainApplication.cs
Normal file
15
TravelMateAdmin/Platforms/Android/MainApplication.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.Runtime;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
[Application]
|
||||||
|
public class MainApplication : MauiApplication
|
||||||
|
{
|
||||||
|
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
|
||||||
|
: base(handle, ownership)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#512BD4</color>
|
||||||
|
<color name="colorPrimaryDark">#2B0B98</color>
|
||||||
|
<color name="colorAccent">#2B0B98</color>
|
||||||
|
</resources>
|
||||||
9
TravelMateAdmin/Platforms/MacCatalyst/AppDelegate.cs
Normal file
9
TravelMateAdmin/Platforms/MacCatalyst/AppDelegate.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Foundation;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : MauiUIApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
14
TravelMateAdmin/Platforms/MacCatalyst/Entitlements.plist
Normal file
14
TravelMateAdmin/Platforms/MacCatalyst/Entitlements.plist
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
|
||||||
|
<dict>
|
||||||
|
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
40
TravelMateAdmin/Platforms/MacCatalyst/Info.plist
Normal file
40
TravelMateAdmin/Platforms/MacCatalyst/Info.plist
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<!-- The Mac App Store requires you specify if the app uses encryption. -->
|
||||||
|
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
|
||||||
|
<!-- <key>ITSAppUsesNonExemptEncryption</key> -->
|
||||||
|
<!-- Please indicate <true/> or <false/> here. -->
|
||||||
|
|
||||||
|
<!-- Specify the category for your app here. -->
|
||||||
|
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
|
||||||
|
<!-- <key>LSApplicationCategoryType</key> -->
|
||||||
|
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
|
||||||
|
<key>UIDeviceFamily</key>
|
||||||
|
<array>
|
||||||
|
<integer>2</integer>
|
||||||
|
</array>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string>public.app-category.lifestyle</string>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>XSAppIconAssets</key>
|
||||||
|
<string>Assets.xcassets/appicon.appiconset</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
15
TravelMateAdmin/Platforms/MacCatalyst/Program.cs
Normal file
15
TravelMateAdmin/Platforms/MacCatalyst/Program.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using ObjCRuntime;
|
||||||
|
using UIKit;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
// This is the main entry point of the application.
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||||
|
// you can specify it here.
|
||||||
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
|
}
|
||||||
|
}
|
||||||
8
TravelMateAdmin/Platforms/Windows/App.xaml
Normal file
8
TravelMateAdmin/Platforms/Windows/App.xaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<maui:MauiWinUIApplication
|
||||||
|
x:Class="TravelMateAdmin.WinUI.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:maui="using:Microsoft.Maui"
|
||||||
|
xmlns:local="using:TravelMateAdmin.WinUI">
|
||||||
|
|
||||||
|
</maui:MauiWinUIApplication>
|
||||||
24
TravelMateAdmin/Platforms/Windows/App.xaml.cs
Normal file
24
TravelMateAdmin/Platforms/Windows/App.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
|
||||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.WinUI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : MauiWinUIApplication
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
|
/// </summary>
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
|
|
||||||
46
TravelMateAdmin/Platforms/Windows/Package.appxmanifest
Normal file
46
TravelMateAdmin/Platforms/Windows/Package.appxmanifest
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||||
|
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||||
|
IgnorableNamespaces="uap rescap">
|
||||||
|
|
||||||
|
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
|
||||||
|
|
||||||
|
<mp:PhoneIdentity PhoneProductId="DF9B5AEA-A739-4C2A-8B2A-7275B002DFE5" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>$placeholder$</DisplayName>
|
||||||
|
<PublisherDisplayName>User Name</PublisherDisplayName>
|
||||||
|
<Logo>$placeholder$.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||||
|
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate" />
|
||||||
|
</Resources>
|
||||||
|
|
||||||
|
<Applications>
|
||||||
|
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="$placeholder$"
|
||||||
|
Description="$placeholder$"
|
||||||
|
Square150x150Logo="$placeholder$.png"
|
||||||
|
Square44x44Logo="$placeholder$.png"
|
||||||
|
BackgroundColor="transparent">
|
||||||
|
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
|
||||||
|
<uap:SplashScreen Image="$placeholder$.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<rescap:Capability Name="runFullTrust" />
|
||||||
|
</Capabilities>
|
||||||
|
|
||||||
|
</Package>
|
||||||
17
TravelMateAdmin/Platforms/Windows/app.manifest
Normal file
17
TravelMateAdmin/Platforms/Windows/app.manifest
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="TravelMateAdmin.WinUI.app"/>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<!-- The combination of below two tags have the following effect:
|
||||||
|
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||||
|
2) System < Windows 10 Anniversary Update
|
||||||
|
-->
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||||
|
|
||||||
|
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
</assembly>
|
||||||
9
TravelMateAdmin/Platforms/iOS/AppDelegate.cs
Normal file
9
TravelMateAdmin/Platforms/iOS/AppDelegate.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Foundation;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : MauiUIApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
32
TravelMateAdmin/Platforms/iOS/Info.plist
Normal file
32
TravelMateAdmin/Platforms/iOS/Info.plist
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIDeviceFamily</key>
|
||||||
|
<array>
|
||||||
|
<integer>1</integer>
|
||||||
|
<integer>2</integer>
|
||||||
|
</array>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>XSAppIconAssets</key>
|
||||||
|
<string>Assets.xcassets/appicon.appiconset</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
15
TravelMateAdmin/Platforms/iOS/Program.cs
Normal file
15
TravelMateAdmin/Platforms/iOS/Program.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using ObjCRuntime;
|
||||||
|
using UIKit;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
// This is the main entry point of the application.
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||||
|
// you can specify it here.
|
||||||
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps.
|
||||||
|
The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK.
|
||||||
|
|
||||||
|
You are responsible for adding extra entries as needed for your application.
|
||||||
|
|
||||||
|
More information: https://aka.ms/maui-privacy-manifest
|
||||||
|
-->
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>C617.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>35F9.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>E174.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<!--
|
||||||
|
The entry below is only needed when you're using the Preferences API in your app.
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>CA92.1</string>
|
||||||
|
</array>
|
||||||
|
</dict> -->
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
8
TravelMateAdmin/Properties/launchSettings.json
Normal file
8
TravelMateAdmin/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Windows Machine": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"nativeDebugging": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
TravelMateAdmin/Resources/AppIcon/appicon.svg
Normal file
4
TravelMateAdmin/Resources/AppIcon/appicon.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 231 B |
8
TravelMateAdmin/Resources/AppIcon/appiconfg.svg
Normal file
8
TravelMateAdmin/Resources/AppIcon/appiconfg.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
TravelMateAdmin/Resources/Fonts/OpenSans-Regular.ttf
Normal file
BIN
TravelMateAdmin/Resources/Fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
BIN
TravelMateAdmin/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
BIN
TravelMateAdmin/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
Binary file not shown.
BIN
TravelMateAdmin/Resources/Images/dotnet_bot.png
Normal file
BIN
TravelMateAdmin/Resources/Images/dotnet_bot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
15
TravelMateAdmin/Resources/Raw/AboutAssets.txt
Normal file
15
TravelMateAdmin/Resources/Raw/AboutAssets.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Any raw assets you want to be deployed with your application can be placed in
|
||||||
|
this directory (and child directories). Deployment of the asset to your application
|
||||||
|
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||||
|
|
||||||
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
|
|
||||||
|
These files will be deployed with your package and will be accessible using Essentials:
|
||||||
|
|
||||||
|
async Task LoadMauiAsset()
|
||||||
|
{
|
||||||
|
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||||
|
using var reader = new StreamReader(stream);
|
||||||
|
|
||||||
|
var contents = reader.ReadToEnd();
|
||||||
|
}
|
||||||
8
TravelMateAdmin/Resources/Splash/splash.svg
Normal file
8
TravelMateAdmin/Resources/Splash/splash.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
44
TravelMateAdmin/Resources/Styles/Colors.xaml
Normal file
44
TravelMateAdmin/Resources/Styles/Colors.xaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||||
|
|
||||||
|
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml -->
|
||||||
|
|
||||||
|
<Color x:Key="Primary">#512BD4</Color>
|
||||||
|
<Color x:Key="PrimaryDark">#ac99ea</Color>
|
||||||
|
<Color x:Key="PrimaryDarkText">#242424</Color>
|
||||||
|
<Color x:Key="Secondary">#DFD8F7</Color>
|
||||||
|
<Color x:Key="SecondaryDarkText">#9880e5</Color>
|
||||||
|
<Color x:Key="Tertiary">#2B0B98</Color>
|
||||||
|
|
||||||
|
<Color x:Key="White">White</Color>
|
||||||
|
<Color x:Key="Black">Black</Color>
|
||||||
|
<Color x:Key="Magenta">#D600AA</Color>
|
||||||
|
<Color x:Key="MidnightBlue">#190649</Color>
|
||||||
|
<Color x:Key="OffBlack">#1f1f1f</Color>
|
||||||
|
|
||||||
|
<Color x:Key="Gray100">#E1E1E1</Color>
|
||||||
|
<Color x:Key="Gray200">#C8C8C8</Color>
|
||||||
|
<Color x:Key="Gray300">#ACACAC</Color>
|
||||||
|
<Color x:Key="Gray400">#919191</Color>
|
||||||
|
<Color x:Key="Gray500">#6E6E6E</Color>
|
||||||
|
<Color x:Key="Gray600">#404040</Color>
|
||||||
|
<Color x:Key="Gray900">#212121</Color>
|
||||||
|
<Color x:Key="Gray950">#141414</Color>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
|
||||||
|
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
|
||||||
|
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
|
||||||
|
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
|
||||||
|
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
|
||||||
|
</ResourceDictionary>
|
||||||
434
TravelMateAdmin/Resources/Styles/Styles.xaml
Normal file
434
TravelMateAdmin/Resources/Styles/Styles.xaml
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||||
|
|
||||||
|
<Style TargetType="ActivityIndicator">
|
||||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="IndicatorView">
|
||||||
|
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
|
||||||
|
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Border">
|
||||||
|
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="StrokeShape" Value="Rectangle"/>
|
||||||
|
<Setter Property="StrokeThickness" Value="1"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="BoxView">
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="BorderWidth" Value="0"/>
|
||||||
|
<Setter Property="CornerRadius" Value="8"/>
|
||||||
|
<Setter Property="Padding" Value="14,10"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="CheckBox">
|
||||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DatePicker">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Editor">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Entry">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="ImageButton">
|
||||||
|
<Setter Property="Opacity" Value="1" />
|
||||||
|
<Setter Property="BorderColor" Value="Transparent"/>
|
||||||
|
<Setter Property="BorderWidth" Value="0"/>
|
||||||
|
<Setter Property="CornerRadius" Value="0"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="Opacity" Value="0.5" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Label">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Label" x:Key="Headline">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="FontSize" Value="32" />
|
||||||
|
<Setter Property="HorizontalOptions" Value="Center" />
|
||||||
|
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Label" x:Key="SubHeadline">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="FontSize" Value="24" />
|
||||||
|
<Setter Property="HorizontalOptions" Value="Center" />
|
||||||
|
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Picker">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="ProgressBar">
|
||||||
|
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="RadioButton">
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="RefreshView">
|
||||||
|
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="SearchBar">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||||
|
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="SearchHandler">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Shadow">
|
||||||
|
<Setter Property="Radius" Value="15" />
|
||||||
|
<Setter Property="Opacity" Value="0.5" />
|
||||||
|
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="Offset" Value="10,10" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Slider">
|
||||||
|
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||||
|
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="SwipeItem">
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Switch">
|
||||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{StaticResource White}" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="On">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Off">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TimePicker">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<Style TargetType="TitleBar">
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="32"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="TitleActiveStates">
|
||||||
|
<VisualState x:Name="TitleBarTitleActive">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="TitleBarTitleInactive">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||||
|
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Style TargetType="Page" ApplyToDerivedTypes="True">
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Shell" ApplyToDerivedTypes="True">
|
||||||
|
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||||
|
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||||
|
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||||
|
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="Shell.NavBarHasShadow" Value="False" />
|
||||||
|
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||||
|
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="NavigationPage">
|
||||||
|
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||||
|
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TabbedPage">
|
||||||
|
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
317
TravelMateAdmin/Services/DatabaseService.cs
Normal file
317
TravelMateAdmin/Services/DatabaseService.cs
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
using MySqlConnector;
|
||||||
|
using TravelMateAdmin.Models;
|
||||||
|
using TravelMateAdmin.Configuration;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.Services;
|
||||||
|
|
||||||
|
public class DatabaseService : IDatabaseService
|
||||||
|
{
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
|
public DatabaseService()
|
||||||
|
{
|
||||||
|
// Utilise la configuration depuis AppSettings
|
||||||
|
_connectionString = AppSettings.GetConnectionString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseService(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Connection
|
||||||
|
|
||||||
|
public async Task<bool> TestConnectionAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Messages
|
||||||
|
|
||||||
|
public async Task<List<Message>> GetAllMessagesAsync()
|
||||||
|
{
|
||||||
|
var messages = new List<Message>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT id, nom, prenom, email, message, done, created_at FROM messages ORDER BY created_at DESC";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
using var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
messages.Add(new Message
|
||||||
|
{
|
||||||
|
Id = reader.GetInt32("id"),
|
||||||
|
Nom = reader.GetString("nom"),
|
||||||
|
Prenom = reader.GetString("prenom"),
|
||||||
|
Email = reader.GetString("email"),
|
||||||
|
MessageText = reader.GetString("message"),
|
||||||
|
Done = reader.GetBoolean("done"),
|
||||||
|
CreatedAt = reader.GetDateTime("created_at")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting messages: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Message>> GetMessagesFilteredAsync(bool? isDone)
|
||||||
|
{
|
||||||
|
if (isDone == null)
|
||||||
|
return await GetAllMessagesAsync();
|
||||||
|
|
||||||
|
var messages = new List<Message>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT id, nom, prenom, email, message, done, created_at FROM messages WHERE done = @done ORDER BY created_at DESC";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
command.Parameters.AddWithValue("@done", isDone.Value);
|
||||||
|
using var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
messages.Add(new Message
|
||||||
|
{
|
||||||
|
Id = reader.GetInt32("id"),
|
||||||
|
Nom = reader.GetString("nom"),
|
||||||
|
Prenom = reader.GetString("prenom"),
|
||||||
|
Email = reader.GetString("email"),
|
||||||
|
MessageText = reader.GetString("message"),
|
||||||
|
Done = reader.GetBoolean("done"),
|
||||||
|
CreatedAt = reader.GetDateTime("created_at")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting filtered messages: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetMessagesPendingCountAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT COUNT(*) FROM messages WHERE done = 0";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
var result = await command.ExecuteScalarAsync();
|
||||||
|
return Convert.ToInt32(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting pending messages count: {ex.Message}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetMessagesDoneCountAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT COUNT(*) FROM messages WHERE done = 1";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
var result = await command.ExecuteScalarAsync();
|
||||||
|
return Convert.ToInt32(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting done messages count: {ex.Message}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> UpdateMessageStatusAsync(int id, bool done)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "UPDATE messages SET done = @done WHERE id = @id";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
command.Parameters.AddWithValue("@done", done);
|
||||||
|
command.Parameters.AddWithValue("@id", id);
|
||||||
|
|
||||||
|
var rowsAffected = await command.ExecuteNonQueryAsync();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error updating message status: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Support Requests
|
||||||
|
|
||||||
|
public async Task<List<SupportRequest>> GetAllSupportRequestsAsync()
|
||||||
|
{
|
||||||
|
var requests = new List<SupportRequest>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT id, nom, prenom, account_email, contact_email, message, done, created_at FROM support_requests ORDER BY created_at DESC";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
using var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
requests.Add(new SupportRequest
|
||||||
|
{
|
||||||
|
Id = reader.GetInt32("id"),
|
||||||
|
Nom = reader.GetString("nom"),
|
||||||
|
Prenom = reader.GetString("prenom"),
|
||||||
|
AccountEmail = reader.GetString("account_email"),
|
||||||
|
ContactEmail = reader.GetString("contact_email"),
|
||||||
|
MessageText = reader.GetString("message"),
|
||||||
|
Done = reader.GetBoolean("done"),
|
||||||
|
CreatedAt = reader.GetDateTime("created_at")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting support requests: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return requests;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<SupportRequest>> GetSupportRequestsFilteredAsync(bool? isDone)
|
||||||
|
{
|
||||||
|
if (isDone == null)
|
||||||
|
return await GetAllSupportRequestsAsync();
|
||||||
|
|
||||||
|
var requests = new List<SupportRequest>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT id, nom, prenom, account_email, contact_email, message, done, created_at FROM support_requests WHERE done = @done ORDER BY created_at DESC";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
command.Parameters.AddWithValue("@done", isDone.Value);
|
||||||
|
using var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
requests.Add(new SupportRequest
|
||||||
|
{
|
||||||
|
Id = reader.GetInt32("id"),
|
||||||
|
Nom = reader.GetString("nom"),
|
||||||
|
Prenom = reader.GetString("prenom"),
|
||||||
|
AccountEmail = reader.GetString("account_email"),
|
||||||
|
ContactEmail = reader.GetString("contact_email"),
|
||||||
|
MessageText = reader.GetString("message"),
|
||||||
|
Done = reader.GetBoolean("done"),
|
||||||
|
CreatedAt = reader.GetDateTime("created_at")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting filtered support requests: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return requests;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetSupportRequestsPendingCountAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT COUNT(*) FROM support_requests WHERE done = 0";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
var result = await command.ExecuteScalarAsync();
|
||||||
|
return Convert.ToInt32(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting pending support requests count: {ex.Message}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetSupportRequestsDoneCountAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "SELECT COUNT(*) FROM support_requests WHERE done = 1";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
var result = await command.ExecuteScalarAsync();
|
||||||
|
return Convert.ToInt32(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error getting done support requests count: {ex.Message}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> UpdateSupportRequestStatusAsync(int id, bool done)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var connection = new MySqlConnection(_connectionString);
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var query = "UPDATE support_requests SET done = @done WHERE id = @id";
|
||||||
|
using var command = new MySqlCommand(query, connection);
|
||||||
|
command.Parameters.AddWithValue("@done", done);
|
||||||
|
command.Parameters.AddWithValue("@id", id);
|
||||||
|
|
||||||
|
var rowsAffected = await command.ExecuteNonQueryAsync();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error updating support request status: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
23
TravelMateAdmin/Services/IDatabaseService.cs
Normal file
23
TravelMateAdmin/Services/IDatabaseService.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using TravelMateAdmin.Models;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.Services;
|
||||||
|
|
||||||
|
public interface IDatabaseService
|
||||||
|
{
|
||||||
|
// Messages
|
||||||
|
Task<List<Message>> GetAllMessagesAsync();
|
||||||
|
Task<List<Message>> GetMessagesFilteredAsync(bool? isDone);
|
||||||
|
Task<int> GetMessagesPendingCountAsync();
|
||||||
|
Task<int> GetMessagesDoneCountAsync();
|
||||||
|
Task<bool> UpdateMessageStatusAsync(int id, bool done);
|
||||||
|
|
||||||
|
// Support Requests
|
||||||
|
Task<List<SupportRequest>> GetAllSupportRequestsAsync();
|
||||||
|
Task<List<SupportRequest>> GetSupportRequestsFilteredAsync(bool? isDone);
|
||||||
|
Task<int> GetSupportRequestsPendingCountAsync();
|
||||||
|
Task<int> GetSupportRequestsDoneCountAsync();
|
||||||
|
Task<bool> UpdateSupportRequestStatusAsync(int id, bool done);
|
||||||
|
|
||||||
|
// Connection
|
||||||
|
Task<bool> TestConnectionAsync();
|
||||||
|
}
|
||||||
66
TravelMateAdmin/TravelMateAdmin.csproj
Normal file
66
TravelMateAdmin/TravelMateAdmin.csproj
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
|
||||||
|
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net10.0-windows10.0.19041.0</TargetFrameworks>
|
||||||
|
|
||||||
|
<!-- Note for MacCatalyst:
|
||||||
|
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
|
||||||
|
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
|
||||||
|
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
|
||||||
|
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
|
||||||
|
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
|
||||||
|
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>TravelMateAdmin</RootNamespace>
|
||||||
|
<UseMaui>true</UseMaui>
|
||||||
|
<SingleProject>true</SingleProject>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<!-- Display name -->
|
||||||
|
<ApplicationTitle>TravelMateAdmin</ApplicationTitle>
|
||||||
|
|
||||||
|
<!-- App Identifier -->
|
||||||
|
<ApplicationId>com.companyname.travelmateadmin</ApplicationId>
|
||||||
|
|
||||||
|
<!-- Versions -->
|
||||||
|
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||||
|
<ApplicationVersion>1</ApplicationVersion>
|
||||||
|
|
||||||
|
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||||
|
<WindowsPackageType>None</WindowsPackageType>
|
||||||
|
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||||
|
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- App Icon -->
|
||||||
|
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
|
||||||
|
|
||||||
|
<!-- Splash Screen -->
|
||||||
|
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<MauiImage Include="Resources\Images\*" />
|
||||||
|
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
|
||||||
|
|
||||||
|
<!-- Custom Fonts -->
|
||||||
|
<MauiFont Include="Resources\Fonts\*" />
|
||||||
|
|
||||||
|
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
|
||||||
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.0" />
|
||||||
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
||||||
|
<PackageReference Include="MySqlConnector" Version="2.4.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
76
TravelMateAdmin/ViewModels/DashboardViewModel.cs
Normal file
76
TravelMateAdmin/ViewModels/DashboardViewModel.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using TravelMateAdmin.Services;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.ViewModels;
|
||||||
|
|
||||||
|
public partial class DashboardViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly IDatabaseService _databaseService;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private int messagesPending;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private int messagesDone;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private int supportRequestsPending;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private int supportRequestsDone;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool isLoading;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string connectionStatus = "Non connecté";
|
||||||
|
|
||||||
|
public DashboardViewModel(IDatabaseService databaseService)
|
||||||
|
{
|
||||||
|
_databaseService = databaseService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task LoadDashboardAsync()
|
||||||
|
{
|
||||||
|
IsLoading = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Test connection
|
||||||
|
var isConnected = await _databaseService.TestConnectionAsync();
|
||||||
|
ConnectionStatus = isConnected ? "✓ Connecté" : "✗ Déconnecté";
|
||||||
|
|
||||||
|
if (isConnected)
|
||||||
|
{
|
||||||
|
// Load stats
|
||||||
|
MessagesPending = await _databaseService.GetMessagesPendingCountAsync();
|
||||||
|
MessagesDone = await _databaseService.GetMessagesDoneCountAsync();
|
||||||
|
SupportRequestsPending = await _databaseService.GetSupportRequestsPendingCountAsync();
|
||||||
|
SupportRequestsDone = await _databaseService.GetSupportRequestsDoneCountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error loading dashboard: {ex.Message}");
|
||||||
|
ConnectionStatus = "✗ Erreur de connexion";
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task NavigateToMessagesAsync()
|
||||||
|
{
|
||||||
|
await Shell.Current.GoToAsync("//MessagesPage");
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task NavigateToSupportAsync()
|
||||||
|
{
|
||||||
|
await Shell.Current.GoToAsync("//SupportPage");
|
||||||
|
}
|
||||||
|
}
|
||||||
83
TravelMateAdmin/ViewModels/MessagesViewModel.cs
Normal file
83
TravelMateAdmin/ViewModels/MessagesViewModel.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using TravelMateAdmin.Models;
|
||||||
|
using TravelMateAdmin.Services;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.ViewModels;
|
||||||
|
|
||||||
|
public partial class MessagesViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly IDatabaseService _databaseService;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private ObservableCollection<Message> messages = new();
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool isLoading;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string selectedFilter = "Tout";
|
||||||
|
|
||||||
|
public List<string> Filters { get; } = new() { "Tout", "À faire", "Fait" };
|
||||||
|
|
||||||
|
public MessagesViewModel(IDatabaseService databaseService)
|
||||||
|
{
|
||||||
|
_databaseService = databaseService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task LoadMessagesAsync()
|
||||||
|
{
|
||||||
|
IsLoading = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool? isDone = SelectedFilter switch
|
||||||
|
{
|
||||||
|
"À faire" => false,
|
||||||
|
"Fait" => true,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
var messagesList = await _databaseService.GetMessagesFilteredAsync(isDone);
|
||||||
|
Messages.Clear();
|
||||||
|
foreach (var message in messagesList)
|
||||||
|
{
|
||||||
|
Messages.Add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error loading messages: {ex.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task ToggleMessageStatusAsync(Message message)
|
||||||
|
{
|
||||||
|
if (message == null) return;
|
||||||
|
|
||||||
|
var success = await _databaseService.UpdateMessageStatusAsync(message.Id, !message.Done);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
message.Done = !message.Done;
|
||||||
|
OnPropertyChanged(nameof(Messages));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task RefreshAsync()
|
||||||
|
{
|
||||||
|
await LoadMessagesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnSelectedFilterChanged(string value)
|
||||||
|
{
|
||||||
|
_ = LoadMessagesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
83
TravelMateAdmin/ViewModels/SupportViewModel.cs
Normal file
83
TravelMateAdmin/ViewModels/SupportViewModel.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using TravelMateAdmin.Models;
|
||||||
|
using TravelMateAdmin.Services;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.ViewModels;
|
||||||
|
|
||||||
|
public partial class SupportViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly IDatabaseService _databaseService;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private ObservableCollection<SupportRequest> supportRequests = new();
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool isLoading;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string selectedFilter = "Tout";
|
||||||
|
|
||||||
|
public List<string> Filters { get; } = new() { "Tout", "À faire", "Fait" };
|
||||||
|
|
||||||
|
public SupportViewModel(IDatabaseService databaseService)
|
||||||
|
{
|
||||||
|
_databaseService = databaseService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task LoadSupportRequestsAsync()
|
||||||
|
{
|
||||||
|
IsLoading = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool? isDone = SelectedFilter switch
|
||||||
|
{
|
||||||
|
"À faire" => false,
|
||||||
|
"Fait" => true,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
var requestsList = await _databaseService.GetSupportRequestsFilteredAsync(isDone);
|
||||||
|
SupportRequests.Clear();
|
||||||
|
foreach (var request in requestsList)
|
||||||
|
{
|
||||||
|
SupportRequests.Add(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error loading support requests: {ex.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task ToggleSupportRequestStatusAsync(SupportRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) return;
|
||||||
|
|
||||||
|
var success = await _databaseService.UpdateSupportRequestStatusAsync(request.Id, !request.Done);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
request.Done = !request.Done;
|
||||||
|
OnPropertyChanged(nameof(SupportRequests));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task RefreshAsync()
|
||||||
|
{
|
||||||
|
await LoadSupportRequestsAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnSelectedFilterChanged(string value)
|
||||||
|
{
|
||||||
|
_ = LoadSupportRequestsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
165
TravelMateAdmin/Views/DashboardPage.xaml
Normal file
165
TravelMateAdmin/Views/DashboardPage.xaml
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:vm="clr-namespace:TravelMateAdmin.ViewModels"
|
||||||
|
x:Class="TravelMateAdmin.Views.DashboardPage"
|
||||||
|
x:DataType="vm:DashboardViewModel"
|
||||||
|
Title="Tableau de Bord"
|
||||||
|
BackgroundColor="{StaticResource Primary}">
|
||||||
|
|
||||||
|
<ContentPage.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<Color x:Key="Primary">#1a1a1a</Color>
|
||||||
|
<Color x:Key="Secondary">#2d2d2d</Color>
|
||||||
|
<Color x:Key="Accent">#5E50D9</Color>
|
||||||
|
<Color x:Key="TextPrimary">#FFFFFF</Color>
|
||||||
|
<Color x:Key="TextSecondary">#B0B0B0</Color>
|
||||||
|
<Color x:Key="Success">#4CAF50</Color>
|
||||||
|
<Color x:Key="Warning">#FFA726</Color>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ContentPage.Resources>
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
<VerticalStackLayout Padding="20" Spacing="20">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<Frame BackgroundColor="{StaticResource Secondary}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="20"
|
||||||
|
HasShadow="True">
|
||||||
|
<Grid RowDefinitions="Auto,Auto" ColumnDefinitions="*,Auto">
|
||||||
|
<Label Text="TravelMate Admin"
|
||||||
|
FontSize="32"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
Grid.Row="0" Grid.Column="0"/>
|
||||||
|
<Label Text="Panneau d'Administration"
|
||||||
|
FontSize="16"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
Grid.Row="1" Grid.Column="0"/>
|
||||||
|
<Label Text="{Binding ConnectionStatus}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource Success}"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"/>
|
||||||
|
</Grid>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
|
<!-- Loading Indicator -->
|
||||||
|
<ActivityIndicator IsRunning="{Binding IsLoading}"
|
||||||
|
IsVisible="{Binding IsLoading}"
|
||||||
|
Color="{StaticResource Accent}"
|
||||||
|
HeightRequest="50"/>
|
||||||
|
|
||||||
|
<!-- Stats Cards -->
|
||||||
|
<Grid ColumnDefinitions="*,*"
|
||||||
|
RowDefinitions="Auto,Auto"
|
||||||
|
ColumnSpacing="15"
|
||||||
|
RowSpacing="15">
|
||||||
|
|
||||||
|
<!-- Messages Pending -->
|
||||||
|
<Frame BackgroundColor="{StaticResource Secondary}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="20"
|
||||||
|
HasShadow="True"
|
||||||
|
Grid.Row="0" Grid.Column="0">
|
||||||
|
<Frame.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer Command="{Binding NavigateToMessagesCommand}"/>
|
||||||
|
</Frame.GestureRecognizers>
|
||||||
|
<VerticalStackLayout Spacing="10">
|
||||||
|
<Label Text="Messages"
|
||||||
|
FontSize="16"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
<Label Text="{Binding MessagesPending}"
|
||||||
|
FontSize="48"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource Warning}"/>
|
||||||
|
<Label Text="En attente"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
|
<!-- Messages Done -->
|
||||||
|
<Frame BackgroundColor="{StaticResource Secondary}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="20"
|
||||||
|
HasShadow="True"
|
||||||
|
Grid.Row="0" Grid.Column="1">
|
||||||
|
<Frame.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer Command="{Binding NavigateToMessagesCommand}"/>
|
||||||
|
</Frame.GestureRecognizers>
|
||||||
|
<VerticalStackLayout Spacing="10">
|
||||||
|
<Label Text="Messages"
|
||||||
|
FontSize="16"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
<Label Text="{Binding MessagesDone}"
|
||||||
|
FontSize="48"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource Success}"/>
|
||||||
|
<Label Text="Traités"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
|
<!-- Support Pending -->
|
||||||
|
<Frame BackgroundColor="{StaticResource Secondary}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="20"
|
||||||
|
HasShadow="True"
|
||||||
|
Grid.Row="1" Grid.Column="0">
|
||||||
|
<Frame.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer Command="{Binding NavigateToSupportCommand}"/>
|
||||||
|
</Frame.GestureRecognizers>
|
||||||
|
<VerticalStackLayout Spacing="10">
|
||||||
|
<Label Text="Support"
|
||||||
|
FontSize="16"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
<Label Text="{Binding SupportRequestsPending}"
|
||||||
|
FontSize="48"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource Warning}"/>
|
||||||
|
<Label Text="En attente"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
|
<!-- Support Done -->
|
||||||
|
<Frame BackgroundColor="{StaticResource Secondary}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="20"
|
||||||
|
HasShadow="True"
|
||||||
|
Grid.Row="1" Grid.Column="1">
|
||||||
|
<Frame.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer Command="{Binding NavigateToSupportCommand}"/>
|
||||||
|
</Frame.GestureRecognizers>
|
||||||
|
<VerticalStackLayout Spacing="10">
|
||||||
|
<Label Text="Support"
|
||||||
|
FontSize="16"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
<Label Text="{Binding SupportRequestsDone}"
|
||||||
|
FontSize="48"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource Success}"/>
|
||||||
|
<Label Text="Traités"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource TextSecondary}"/>
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</Frame>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Refresh Button -->
|
||||||
|
<Button Text="Actualiser"
|
||||||
|
Command="{Binding LoadDashboardCommand}"
|
||||||
|
BackgroundColor="{StaticResource Accent}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
CornerRadius="10"
|
||||||
|
HeightRequest="50"
|
||||||
|
FontSize="16"
|
||||||
|
FontAttributes="Bold"/>
|
||||||
|
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</ContentPage>
|
||||||
21
TravelMateAdmin/Views/DashboardPage.xaml.cs
Normal file
21
TravelMateAdmin/Views/DashboardPage.xaml.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using TravelMateAdmin.ViewModels;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.Views;
|
||||||
|
|
||||||
|
public partial class DashboardPage : ContentPage
|
||||||
|
{
|
||||||
|
private readonly DashboardViewModel _viewModel;
|
||||||
|
|
||||||
|
public DashboardPage(DashboardViewModel viewModel)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
_viewModel = viewModel;
|
||||||
|
BindingContext = _viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
await _viewModel.LoadDashboardCommand.ExecuteAsync(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
143
TravelMateAdmin/Views/MessagesPage.xaml
Normal file
143
TravelMateAdmin/Views/MessagesPage.xaml
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:vm="clr-namespace:TravelMateAdmin.ViewModels"
|
||||||
|
xmlns:models="clr-namespace:TravelMateAdmin.Models"
|
||||||
|
xmlns:converters="clr-namespace:TravelMateAdmin.Converters"
|
||||||
|
x:Class="TravelMateAdmin.Views.MessagesPage"
|
||||||
|
x:DataType="vm:MessagesViewModel"
|
||||||
|
Title="Messages"
|
||||||
|
BackgroundColor="{StaticResource Primary}">
|
||||||
|
|
||||||
|
<ContentPage.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<Color x:Key="Primary">#1a1a1a</Color>
|
||||||
|
<Color x:Key="Secondary">#2d2d2d</Color>
|
||||||
|
<Color x:Key="Accent">#5E50D9</Color>
|
||||||
|
<Color x:Key="TextPrimary">#FFFFFF</Color>
|
||||||
|
<Color x:Key="TextSecondary">#B0B0B0</Color>
|
||||||
|
<Color x:Key="Success">#4CAF50</Color>
|
||||||
|
<Color x:Key="Warning">#FFA726</Color>
|
||||||
|
<Color x:Key="CardBackground">#252525</Color>
|
||||||
|
|
||||||
|
<converters:BoolToStatusTextConverter x:Key="BoolToStatusTextConverter"/>
|
||||||
|
<converters:BoolToColorConverter x:Key="BoolToColorConverter"/>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ContentPage.Resources>
|
||||||
|
|
||||||
|
<Grid RowDefinitions="Auto,Auto,*" Padding="20" RowSpacing="15">
|
||||||
|
|
||||||
|
<!-- Header with Filter -->
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" ColumnSpacing="10">
|
||||||
|
<Label Text="Messages"
|
||||||
|
FontSize="28"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Grid.Column="0"/>
|
||||||
|
|
||||||
|
<Picker ItemsSource="{Binding Filters}"
|
||||||
|
SelectedItem="{Binding SelectedFilter}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
BackgroundColor="{StaticResource Secondary}"
|
||||||
|
WidthRequest="150"
|
||||||
|
Grid.Column="1"/>
|
||||||
|
|
||||||
|
<Button Text="↻"
|
||||||
|
Command="{Binding RefreshCommand}"
|
||||||
|
BackgroundColor="{StaticResource Accent}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
WidthRequest="50"
|
||||||
|
HeightRequest="50"
|
||||||
|
CornerRadius="25"
|
||||||
|
FontSize="20"
|
||||||
|
Grid.Column="2"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Loading Indicator -->
|
||||||
|
<ActivityIndicator IsRunning="{Binding IsLoading}"
|
||||||
|
IsVisible="{Binding IsLoading}"
|
||||||
|
Color="{StaticResource Accent}"
|
||||||
|
HeightRequest="50"
|
||||||
|
Grid.Row="1"/>
|
||||||
|
|
||||||
|
<!-- Messages List -->
|
||||||
|
<CollectionView ItemsSource="{Binding Messages}"
|
||||||
|
Grid.Row="2"
|
||||||
|
SelectionMode="None">
|
||||||
|
<CollectionView.EmptyView>
|
||||||
|
<VerticalStackLayout HorizontalOptions="Center"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Spacing="10">
|
||||||
|
<Label Text="Aucun message"
|
||||||
|
FontSize="20"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
HorizontalOptions="Center"/>
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</CollectionView.EmptyView>
|
||||||
|
|
||||||
|
<CollectionView.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="models:Message">
|
||||||
|
<Frame BackgroundColor="{StaticResource CardBackground}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="15"
|
||||||
|
Margin="0,5"
|
||||||
|
HasShadow="True">
|
||||||
|
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto"
|
||||||
|
ColumnDefinitions="*,Auto"
|
||||||
|
RowSpacing="8">
|
||||||
|
|
||||||
|
<!-- Name and Date -->
|
||||||
|
<Label Text="{Binding FullName}"
|
||||||
|
FontSize="18"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
Grid.Row="0" Grid.Column="0"/>
|
||||||
|
<Label Text="{Binding CreatedAtFormatted}"
|
||||||
|
FontSize="12"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
Grid.Row="0" Grid.Column="1"/>
|
||||||
|
|
||||||
|
<!-- Email -->
|
||||||
|
<Label Text="{Binding Email}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource Accent}"
|
||||||
|
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Message -->
|
||||||
|
<Label Text="{Binding MessageText}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
LineBreakMode="WordWrap"
|
||||||
|
MaxLines="5"
|
||||||
|
Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Separator -->
|
||||||
|
<BoxView BackgroundColor="{StaticResource Secondary}"
|
||||||
|
HeightRequest="1"
|
||||||
|
Margin="0,8"
|
||||||
|
Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Status and Action -->
|
||||||
|
<Label Text="{Binding StatusText}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource Warning}"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Grid.Row="4" Grid.Column="0"/>
|
||||||
|
|
||||||
|
<Button Text="{Binding Done, Converter={StaticResource BoolToStatusTextConverter}}"
|
||||||
|
Command="{Binding Source={RelativeSource AncestorType={x:Type vm:MessagesViewModel}}, Path=ToggleMessageStatusCommand}"
|
||||||
|
CommandParameter="{Binding .}"
|
||||||
|
BackgroundColor="{Binding Done, Converter={StaticResource BoolToColorConverter}}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
CornerRadius="8"
|
||||||
|
FontSize="14"
|
||||||
|
HeightRequest="40"
|
||||||
|
Grid.Row="4" Grid.Column="1"/>
|
||||||
|
</Grid>
|
||||||
|
</Frame>
|
||||||
|
</DataTemplate>
|
||||||
|
</CollectionView.ItemTemplate>
|
||||||
|
</CollectionView>
|
||||||
|
</Grid>
|
||||||
|
</ContentPage>
|
||||||
21
TravelMateAdmin/Views/MessagesPage.xaml.cs
Normal file
21
TravelMateAdmin/Views/MessagesPage.xaml.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using TravelMateAdmin.ViewModels;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.Views;
|
||||||
|
|
||||||
|
public partial class MessagesPage : ContentPage
|
||||||
|
{
|
||||||
|
private readonly MessagesViewModel _viewModel;
|
||||||
|
|
||||||
|
public MessagesPage(MessagesViewModel viewModel)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
_viewModel = viewModel;
|
||||||
|
BindingContext = _viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
await _viewModel.LoadMessagesCommand.ExecuteAsync(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
149
TravelMateAdmin/Views/SupportPage.xaml
Normal file
149
TravelMateAdmin/Views/SupportPage.xaml
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:vm="clr-namespace:TravelMateAdmin.ViewModels"
|
||||||
|
xmlns:models="clr-namespace:TravelMateAdmin.Models"
|
||||||
|
xmlns:converters="clr-namespace:TravelMateAdmin.Converters"
|
||||||
|
x:Class="TravelMateAdmin.Views.SupportPage"
|
||||||
|
x:DataType="vm:SupportViewModel"
|
||||||
|
Title="Support"
|
||||||
|
BackgroundColor="{StaticResource Primary}">
|
||||||
|
|
||||||
|
<ContentPage.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<Color x:Key="Primary">#1a1a1a</Color>
|
||||||
|
<Color x:Key="Secondary">#2d2d2d</Color>
|
||||||
|
<Color x:Key="Accent">#5E50D9</Color>
|
||||||
|
<Color x:Key="TextPrimary">#FFFFFF</Color>
|
||||||
|
<Color x:Key="TextSecondary">#B0B0B0</Color>
|
||||||
|
<Color x:Key="Success">#4CAF50</Color>
|
||||||
|
<Color x:Key="Warning">#FFA726</Color>
|
||||||
|
<Color x:Key="CardBackground">#252525</Color>
|
||||||
|
|
||||||
|
<converters:BoolToStatusTextConverter x:Key="BoolToStatusTextConverter"/>
|
||||||
|
<converters:BoolToColorConverter x:Key="BoolToColorConverter"/>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ContentPage.Resources>
|
||||||
|
|
||||||
|
<Grid RowDefinitions="Auto,Auto,*" Padding="20" RowSpacing="15">
|
||||||
|
|
||||||
|
<!-- Header with Filter -->
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" ColumnSpacing="10">
|
||||||
|
<Label Text="Demandes Support"
|
||||||
|
FontSize="28"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Grid.Column="0"/>
|
||||||
|
|
||||||
|
<Picker ItemsSource="{Binding Filters}"
|
||||||
|
SelectedItem="{Binding SelectedFilter}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
BackgroundColor="{StaticResource Secondary}"
|
||||||
|
WidthRequest="150"
|
||||||
|
Grid.Column="1"/>
|
||||||
|
|
||||||
|
<Button Text="↻"
|
||||||
|
Command="{Binding RefreshCommand}"
|
||||||
|
BackgroundColor="{StaticResource Accent}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
WidthRequest="50"
|
||||||
|
HeightRequest="50"
|
||||||
|
CornerRadius="25"
|
||||||
|
FontSize="20"
|
||||||
|
Grid.Column="2"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Loading Indicator -->
|
||||||
|
<ActivityIndicator IsRunning="{Binding IsLoading}"
|
||||||
|
IsVisible="{Binding IsLoading}"
|
||||||
|
Color="{StaticResource Accent}"
|
||||||
|
HeightRequest="50"
|
||||||
|
Grid.Row="1"/>
|
||||||
|
|
||||||
|
<!-- Support Requests List -->
|
||||||
|
<CollectionView ItemsSource="{Binding SupportRequests}"
|
||||||
|
Grid.Row="2"
|
||||||
|
SelectionMode="None">
|
||||||
|
<CollectionView.EmptyView>
|
||||||
|
<VerticalStackLayout HorizontalOptions="Center"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Spacing="10">
|
||||||
|
<Label Text="Aucune demande support"
|
||||||
|
FontSize="20"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
HorizontalOptions="Center"/>
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</CollectionView.EmptyView>
|
||||||
|
|
||||||
|
<CollectionView.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="models:SupportRequest">
|
||||||
|
<Frame BackgroundColor="{StaticResource CardBackground}"
|
||||||
|
CornerRadius="10"
|
||||||
|
Padding="15"
|
||||||
|
Margin="0,5"
|
||||||
|
HasShadow="True">
|
||||||
|
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto"
|
||||||
|
ColumnDefinitions="*,Auto"
|
||||||
|
RowSpacing="8">
|
||||||
|
|
||||||
|
<!-- Name and Date -->
|
||||||
|
<Label Text="{Binding FullName}"
|
||||||
|
FontSize="18"
|
||||||
|
FontAttributes="Bold"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
Grid.Row="0" Grid.Column="0"/>
|
||||||
|
<Label Text="{Binding CreatedAtFormatted}"
|
||||||
|
FontSize="12"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
Grid.Row="0" Grid.Column="1"/>
|
||||||
|
|
||||||
|
<!-- Account Email -->
|
||||||
|
<Label Text="{Binding AccountEmail, StringFormat='Compte: {0}'}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource Accent}"
|
||||||
|
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Contact Email -->
|
||||||
|
<Label Text="{Binding ContactEmail, StringFormat='Contact: {0}'}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource Accent}"
|
||||||
|
Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Message -->
|
||||||
|
<Label Text="{Binding MessageText}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource TextSecondary}"
|
||||||
|
LineBreakMode="WordWrap"
|
||||||
|
MaxLines="5"
|
||||||
|
Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Separator -->
|
||||||
|
<BoxView BackgroundColor="{StaticResource Secondary}"
|
||||||
|
HeightRequest="1"
|
||||||
|
Margin="0,8"
|
||||||
|
Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<!-- Status and Action -->
|
||||||
|
<Label Text="{Binding StatusText}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="{StaticResource Warning}"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
Grid.Row="5" Grid.Column="0"/>
|
||||||
|
|
||||||
|
<Button Text="{Binding Done, Converter={StaticResource BoolToStatusTextConverter}}"
|
||||||
|
Command="{Binding Source={RelativeSource AncestorType={x:Type vm:SupportViewModel}}, Path=ToggleSupportRequestStatusCommand}"
|
||||||
|
CommandParameter="{Binding .}"
|
||||||
|
BackgroundColor="{Binding Done, Converter={StaticResource BoolToColorConverter}}"
|
||||||
|
TextColor="{StaticResource TextPrimary}"
|
||||||
|
CornerRadius="8"
|
||||||
|
FontSize="14"
|
||||||
|
HeightRequest="40"
|
||||||
|
Grid.Row="5" Grid.Column="1"/>
|
||||||
|
</Grid>
|
||||||
|
</Frame>
|
||||||
|
</DataTemplate>
|
||||||
|
</CollectionView.ItemTemplate>
|
||||||
|
</CollectionView>
|
||||||
|
</Grid>
|
||||||
|
</ContentPage>
|
||||||
21
TravelMateAdmin/Views/SupportPage.xaml.cs
Normal file
21
TravelMateAdmin/Views/SupportPage.xaml.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using TravelMateAdmin.ViewModels;
|
||||||
|
|
||||||
|
namespace TravelMateAdmin.Views;
|
||||||
|
|
||||||
|
public partial class SupportPage : ContentPage
|
||||||
|
{
|
||||||
|
private readonly SupportViewModel _viewModel;
|
||||||
|
|
||||||
|
public SupportPage(SupportViewModel viewModel)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
_viewModel = viewModel;
|
||||||
|
BindingContext = _viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
await _viewModel.LoadSupportRequestsCommand.ExecuteAsync(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
database_setup.sql
Normal file
52
database_setup.sql
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
-- Script SQL pour créer la base de données TravelMate Admin
|
||||||
|
-- À exécuter dans MySQL/MariaDB
|
||||||
|
|
||||||
|
-- Créer la base de données
|
||||||
|
CREATE DATABASE IF NOT EXISTS travelmateadmin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
USE travelmateadmin;
|
||||||
|
|
||||||
|
-- Table des messages
|
||||||
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
nom VARCHAR(100) NOT NULL,
|
||||||
|
prenom VARCHAR(100) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
done BOOLEAN DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_done (done),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Table des demandes support
|
||||||
|
CREATE TABLE IF NOT EXISTS support_requests (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
nom VARCHAR(100) NOT NULL,
|
||||||
|
prenom VARCHAR(100) NOT NULL,
|
||||||
|
account_email VARCHAR(255) NOT NULL,
|
||||||
|
contact_email VARCHAR(255) NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
done BOOLEAN DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_done (done),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Données de test pour messages
|
||||||
|
INSERT INTO messages (nom, prenom, email, message, done, created_at) VALUES
|
||||||
|
('Dupont', 'Jean', 'jean.dupont@example.com', 'Je souhaite effacer toutes mes données personnelles conformément au RGPD.', FALSE, NOW() - INTERVAL 2 DAY),
|
||||||
|
('Martin', 'Sophie', 'sophie.martin@example.com', 'Pouvez-vous supprimer mon compte et toutes les informations associées ?', FALSE, NOW() - INTERVAL 1 DAY),
|
||||||
|
('Bernard', 'Pierre', 'pierre.bernard@example.com', 'Demande de suppression de données RGPD', TRUE, NOW() - INTERVAL 5 DAY),
|
||||||
|
('Dubois', 'Marie', 'marie.dubois@example.com', 'Bonjour, je voudrais avoir des informations sur vos services.', FALSE, NOW() - INTERVAL 3 HOUR);
|
||||||
|
|
||||||
|
-- Données de test pour support_requests
|
||||||
|
INSERT INTO support_requests (nom, prenom, account_email, contact_email, message, done, created_at) VALUES
|
||||||
|
('Petit', 'Lucas', 'lucas.petit@example.com', 'lucas.contact@example.com', 'Je n''arrive pas à me connecter à mon compte depuis hier.', FALSE, NOW() - INTERVAL 1 DAY),
|
||||||
|
('Roux', 'Emma', 'emma.roux@example.com', 'emma.pro@example.com', 'Mon mot de passe ne fonctionne plus, pouvez-vous m''aider ?', FALSE, NOW() - INTERVAL 6 HOUR),
|
||||||
|
('Moreau', 'Thomas', 'thomas.moreau@example.com', 'thomas.m@example.com', 'Problème de synchronisation des données', TRUE, NOW() - INTERVAL 4 DAY),
|
||||||
|
('Simon', 'Julie', 'julie.simon@example.com', 'julie.s@example.com', 'Question sur la facturation de mon abonnement', FALSE, NOW() - INTERVAL 2 HOUR);
|
||||||
|
|
||||||
|
-- Afficher un résumé
|
||||||
|
SELECT 'Messages créés:' AS info, COUNT(*) AS count FROM messages
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'Support créés:', COUNT(*) FROM support_requests;
|
||||||
Reference in New Issue
Block a user