Add equipment management features (and qr generation support)

This commit is contained in:
ElPoyo
2025-10-21 16:32:18 +02:00
parent ef638d8c8c
commit ae3a1b7227
18 changed files with 4489 additions and 7 deletions

View File

@@ -0,0 +1,128 @@
import 'package:flutter/foundation.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:em2rp/models/alert_model.dart';
class AlertProvider extends ChangeNotifier {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
List<AlertModel> _alerts = [];
// Getters
List<AlertModel> get alerts => _alerts;
/// Nombre d'alertes non lues
int get unreadCount => _alerts.where((alert) => !alert.isRead).length;
/// Alertes non lues uniquement
List<AlertModel> get unreadAlerts => _alerts.where((alert) => !alert.isRead).toList();
/// Alertes de stock critique
List<AlertModel> get lowStockAlerts => _alerts.where((alert) => alert.type == AlertType.lowStock).toList();
/// Alertes de maintenance
List<AlertModel> get maintenanceAlerts => _alerts.where((alert) => alert.type == AlertType.maintenanceDue).toList();
/// Alertes de conflit
List<AlertModel> get conflictAlerts => _alerts.where((alert) => alert.type == AlertType.conflict).toList();
/// Stream des alertes
Stream<List<AlertModel>> get alertsStream {
return _firestore
.collection('alerts')
.orderBy('createdAt', descending: true)
.snapshots()
.map((snapshot) {
_alerts = snapshot.docs
.map((doc) => AlertModel.fromMap(doc.data(), doc.id))
.toList();
return _alerts;
});
}
/// Marquer une alerte comme lue
Future<void> markAsRead(String alertId) async {
try {
await _firestore.collection('alerts').doc(alertId).update({
'isRead': true,
});
notifyListeners();
} catch (e) {
print('Error marking alert as read: $e');
rethrow;
}
}
/// Marquer toutes les alertes comme lues
Future<void> markAllAsRead() async {
try {
final batch = _firestore.batch();
for (var alert in _alerts.where((a) => !a.isRead)) {
batch.update(
_firestore.collection('alerts').doc(alert.id),
{'isRead': true},
);
}
await batch.commit();
notifyListeners();
} catch (e) {
print('Error marking all alerts as read: $e');
rethrow;
}
}
/// Supprimer une alerte
Future<void> deleteAlert(String alertId) async {
try {
await _firestore.collection('alerts').doc(alertId).delete();
notifyListeners();
} catch (e) {
print('Error deleting alert: $e');
rethrow;
}
}
/// Supprimer toutes les alertes lues
Future<void> deleteReadAlerts() async {
try {
final batch = _firestore.batch();
for (var alert in _alerts.where((a) => a.isRead)) {
batch.delete(_firestore.collection('alerts').doc(alert.id));
}
await batch.commit();
notifyListeners();
} catch (e) {
print('Error deleting read alerts: $e');
rethrow;
}
}
/// Créer une alerte (utilisé principalement par les services)
Future<void> createAlert(AlertModel alert) async {
try {
await _firestore.collection('alerts').doc(alert.id).set(alert.toMap());
notifyListeners();
} catch (e) {
print('Error creating alert: $e');
rethrow;
}
}
/// Récupérer les alertes pour un équipement spécifique
Stream<List<AlertModel>> getAlertsForEquipment(String equipmentId) {
return _firestore
.collection('alerts')
.where('equipmentId', isEqualTo: equipmentId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((snapshot) {
return snapshot.docs
.map((doc) => AlertModel.fromMap(doc.data(), doc.id))
.toList();
});
}
}

View File

@@ -0,0 +1,217 @@
import 'package:flutter/foundation.dart';
import 'package:em2rp/models/equipment_model.dart';
import 'package:em2rp/services/equipment_service.dart';
class EquipmentProvider extends ChangeNotifier {
final EquipmentService _service = EquipmentService();
List<EquipmentModel> _equipment = [];
List<String> _models = [];
List<String> _brands = [];
EquipmentCategory? _selectedCategory;
EquipmentStatus? _selectedStatus;
String? _selectedModel;
String _searchQuery = '';
// Getters
List<EquipmentModel> get equipment => _equipment;
List<String> get models => _models;
List<String> get brands => _brands;
EquipmentCategory? get selectedCategory => _selectedCategory;
EquipmentStatus? get selectedStatus => _selectedStatus;
String? get selectedModel => _selectedModel;
String get searchQuery => _searchQuery;
/// Stream des équipements avec filtres appliqués
Stream<List<EquipmentModel>> get equipmentStream {
return _service.getEquipment(
category: _selectedCategory,
status: _selectedStatus,
model: _selectedModel,
searchQuery: _searchQuery,
);
}
/// Charger tous les modèles uniques
Future<void> loadModels() async {
try {
_models = await _service.getAllModels();
notifyListeners();
} catch (e) {
print('Error loading models: $e');
rethrow;
}
}
/// Charger toutes les marques uniques
Future<void> loadBrands() async {
try {
_brands = await _service.getAllBrands();
notifyListeners();
} catch (e) {
print('Error loading brands: $e');
rethrow;
}
}
/// Charger les modèles filtrés par marque
Future<List<String>> loadModelsByBrand(String brand) async {
try {
return await _service.getModelsByBrand(brand);
} catch (e) {
print('Error loading models by brand: $e');
rethrow;
}
}
/// Ajouter un équipement
Future<void> addEquipment(EquipmentModel equipment) async {
try {
await _service.createEquipment(equipment);
// Recharger les modèles si un nouveau modèle a été ajouté
if (equipment.model != null && !_models.contains(equipment.model)) {
await loadModels();
}
} catch (e) {
print('Error adding equipment: $e');
rethrow;
}
}
/// Mettre à jour un équipement
Future<void> updateEquipment(String id, Map<String, dynamic> data) async {
try {
await _service.updateEquipment(id, data);
// Recharger les modèles si le modèle a changé
if (data.containsKey('model')) {
await loadModels();
}
} catch (e) {
print('Error updating equipment: $e');
rethrow;
}
}
/// Supprimer un équipement
Future<void> deleteEquipment(String id) async {
try {
await _service.deleteEquipment(id);
} catch (e) {
print('Error deleting equipment: $e');
rethrow;
}
}
/// Récupérer un équipement par ID
Future<EquipmentModel?> getEquipmentById(String id) async {
try {
return await _service.getEquipmentById(id);
} catch (e) {
print('Error getting equipment: $e');
rethrow;
}
}
/// Trouver des alternatives disponibles
Future<List<EquipmentModel>> findAlternatives(
String model,
DateTime startDate,
DateTime endDate,
) async {
try {
return await _service.findAlternatives(model, startDate, endDate);
} catch (e) {
print('Error finding alternatives: $e');
rethrow;
}
}
/// Vérifier la disponibilité d'un équipement
Future<List<String>> checkAvailability(
String equipmentId,
DateTime startDate,
DateTime endDate,
) async {
try {
return await _service.checkAvailability(equipmentId, startDate, endDate);
} catch (e) {
print('Error checking availability: $e');
rethrow;
}
}
/// Mettre à jour le stock d'un consommable
Future<void> updateStock(String id, int quantityChange) async {
try {
await _service.updateStock(id, quantityChange);
} catch (e) {
print('Error updating stock: $e');
rethrow;
}
}
/// Vérifier les stocks critiques
Future<void> checkCriticalStock() async {
try {
await _service.checkCriticalStock();
} catch (e) {
print('Error checking critical stock: $e');
rethrow;
}
}
/// Générer les données du QR code
String generateQRCodeData(String equipmentId) {
return _service.generateQRCodeData(equipmentId);
}
/// Vérifier si un ID est unique
Future<bool> isIdUnique(String id) async {
try {
return await _service.isIdUnique(id);
} catch (e) {
print('Error checking ID uniqueness: $e');
rethrow;
}
}
// === FILTRES ===
/// Définir la catégorie sélectionnée
void setSelectedCategory(EquipmentCategory? category) {
_selectedCategory = category;
notifyListeners();
}
/// Définir le statut sélectionné
void setSelectedStatus(EquipmentStatus? status) {
_selectedStatus = status;
notifyListeners();
}
/// Définir le modèle sélectionné
void setSelectedModel(String? model) {
_selectedModel = model;
notifyListeners();
}
/// Définir la recherche
void setSearchQuery(String query) {
_searchQuery = query;
notifyListeners();
}
/// Réinitialiser tous les filtres
void resetFilters() {
_selectedCategory = null;
_selectedStatus = null;
_selectedModel = null;
_searchQuery = '';
notifyListeners();
}
}

View File

@@ -30,9 +30,7 @@ class EventProvider with ChangeNotifier {
for (var doc in eventsSnapshot.docs) {
try {
final data = doc.data() as Map<String, dynamic>;
print('Processing event ${doc.id}: ${data['Name'] ?? 'Unknown'}');
final event = EventModel.fromMap(data, doc.id);
final event = EventModel.fromMap(data, doc.id);
allEvents.add(event);
} catch (e) {
print('Failed to parse event ${doc.id}: $e');
@@ -41,8 +39,6 @@ class EventProvider with ChangeNotifier {
}
}
print('Successfully parsed ${allEvents.length} events, failed: $failedCount');
// Filtrage amélioré pour les utilisateurs non-admin
if (canViewAllEvents) {
_events = allEvents;
@@ -63,8 +59,6 @@ class EventProvider with ChangeNotifier {
return isInWorkforce;
}).toList();
print('Non-admin user: showing ${_events.length} events out of ${allEvents.length}');
}
_isLoading = false;

View File

@@ -0,0 +1,106 @@
import 'package:flutter/foundation.dart';
import 'package:em2rp/models/maintenance_model.dart';
import 'package:em2rp/services/maintenance_service.dart';
class MaintenanceProvider extends ChangeNotifier {
final MaintenanceService _service = MaintenanceService();
List<MaintenanceModel> _maintenances = [];
// Getters
List<MaintenanceModel> get maintenances => _maintenances;
/// Stream des maintenances pour un équipement spécifique
Stream<List<MaintenanceModel>> getMaintenancesStream(String equipmentId) {
return _service.getMaintenances(equipmentId);
}
/// Stream de toutes les maintenances
Stream<List<MaintenanceModel>> get allMaintenancesStream {
return _service.getAllMaintenances();
}
/// Créer une nouvelle maintenance
Future<void> createMaintenance(MaintenanceModel maintenance) async {
try {
await _service.createMaintenance(maintenance);
notifyListeners();
} catch (e) {
print('Error creating maintenance: $e');
rethrow;
}
}
/// Mettre à jour une maintenance
Future<void> updateMaintenance(String id, Map<String, dynamic> data) async {
try {
await _service.updateMaintenance(id, data);
notifyListeners();
} catch (e) {
print('Error updating maintenance: $e');
rethrow;
}
}
/// Supprimer une maintenance
Future<void> deleteMaintenance(String id) async {
try {
await _service.deleteMaintenance(id);
notifyListeners();
} catch (e) {
print('Error deleting maintenance: $e');
rethrow;
}
}
/// Récupérer une maintenance par ID
Future<MaintenanceModel?> getMaintenanceById(String id) async {
try {
return await _service.getMaintenanceById(id);
} catch (e) {
print('Error getting maintenance: $e');
rethrow;
}
}
/// Marquer une maintenance comme complétée
Future<void> completeMaintenance(
String id, {
String? performedBy,
double? cost,
}) async {
try {
await _service.completeMaintenance(id, performedBy: performedBy, cost: cost);
notifyListeners();
} catch (e) {
print('Error completing maintenance: $e');
rethrow;
}
}
/// Vérifier les maintenances à venir
Future<void> checkUpcomingMaintenances() async {
try {
await _service.checkUpcomingMaintenances();
} catch (e) {
print('Error checking upcoming maintenances: $e');
rethrow;
}
}
/// Récupérer les maintenances en retard
List<MaintenanceModel> get overdueMaintances {
return _maintenances.where((m) => m.isOverdue).toList();
}
/// Récupérer les maintenances complétées
List<MaintenanceModel> get completedMaintenances {
return _maintenances.where((m) => m.isCompleted).toList();
}
/// Récupérer les maintenances à venir
List<MaintenanceModel> get upcomingMaintenances {
return _maintenances.where((m) => !m.isCompleted && !m.isOverdue).toList();
}
}