Add equipment management features (and qr generation support)
This commit is contained in:
128
em2rp/lib/providers/alert_provider.dart
Normal file
128
em2rp/lib/providers/alert_provider.dart
Normal 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
217
em2rp/lib/providers/equipment_provider.dart
Normal file
217
em2rp/lib/providers/equipment_provider.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
106
em2rp/lib/providers/maintenance_provider.dart
Normal file
106
em2rp/lib/providers/maintenance_provider.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user