Base solide de la page calendar, commit avant refacto

This commit is contained in:
2025-05-18 20:01:26 +02:00
parent 8bd80dc7f3
commit 62c6125d8c
4 changed files with 176 additions and 52 deletions

View File

@ -1,4 +1,5 @@
import 'package:em2rp/providers/users_provider.dart'; import 'package:em2rp/providers/users_provider.dart';
import 'package:em2rp/providers/event_provider.dart';
import 'package:em2rp/utils/auth_guard_widget.dart'; import 'package:em2rp/utils/auth_guard_widget.dart';
import 'package:em2rp/views/calendar_page.dart'; import 'package:em2rp/views/calendar_page.dart';
import 'package:em2rp/views/login_page.dart'; import 'package:em2rp/views/login_page.dart';
@ -36,6 +37,11 @@ void main() async {
ChangeNotifierProvider<UsersProvider>( ChangeNotifierProvider<UsersProvider>(
create: (context) => UsersProvider(context.read<UserService>()), create: (context) => UsersProvider(context.read<UserService>()),
), ),
// EventProvider pour la gestion des événements
ChangeNotifierProvider<EventProvider>(
create: (context) => EventProvider(),
),
], ],
child: const MyApp(), child: const MyApp(),
), ),

View File

@ -13,6 +13,7 @@ class EventModel {
final String eventTypeId; final String eventTypeId;
final String customerId; final String customerId;
final LatLng address; final LatLng address;
final List<String> workforce;
EventModel({ EventModel({
required this.id, required this.id,
@ -26,37 +27,56 @@ class EventModel {
required this.eventTypeId, required this.eventTypeId,
required this.customerId, required this.customerId,
required this.address, required this.address,
required this.workforce,
}); });
factory EventModel.fromMap(Map<String, dynamic> map, String id) { factory EventModel.fromMap(Map<String, dynamic> map, String id) {
final GeoPoint geoPoint = map['address'] as GeoPoint; final GeoPoint? geoPoint = map['Address'] as GeoPoint?;
final List<dynamic> workforceRefs = map['workforce'] ?? [];
final Timestamp? startTimestamp = map['StartDateTime'] as Timestamp?;
final Timestamp? endTimestamp = map['EndDateTime'] as Timestamp?;
return EventModel( return EventModel(
id: id, id: id,
name: map['name'] ?? '', name: map['Name'] ?? '',
description: map['description'] ?? '', description: map['Description'] ?? '',
startDateTime: (map['startDateTime'] as Timestamp).toDate(), startDateTime: startTimestamp?.toDate() ?? DateTime.now(),
endDateTime: (map['endDateTime'] as Timestamp).toDate(), endDateTime: endTimestamp?.toDate() ??
price: (map['price'] ?? 0.0).toDouble(), DateTime.now().add(const Duration(hours: 1)),
installationTime: map['installationTime'] ?? 0, price: (map['Price'] ?? 0.0).toDouble(),
disassemblyTime: map['disassemblyTime'] ?? 0, installationTime: map['InstallationTime'] ?? 0,
eventTypeId: map['eventType'] ?? '', disassemblyTime: map['DisassemblyTime'] ?? 0,
customerId: map['customer'] ?? '', eventTypeId: map['EventType'] is DocumentReference
address: LatLng(geoPoint.latitude, geoPoint.longitude), ? (map['EventType'] as DocumentReference).id
: '',
customerId: map['customer'] is DocumentReference
? (map['customer'] as DocumentReference).id
: '',
address: geoPoint != null
? LatLng(geoPoint.latitude, geoPoint.longitude)
: const LatLng(0, 0),
workforce: workforceRefs.map((ref) {
if (ref is DocumentReference) {
return ref.id;
}
return ref.toString();
}).toList(),
); );
} }
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
'name': name, 'Name': name,
'description': description, 'Description': description,
'startDateTime': Timestamp.fromDate(startDateTime), 'StartDateTime': Timestamp.fromDate(startDateTime),
'endDateTime': Timestamp.fromDate(endDateTime), 'EndDateTime': Timestamp.fromDate(endDateTime),
'price': price, 'Price': price,
'installationTime': installationTime, 'InstallationTime': installationTime,
'disassemblyTime': disassemblyTime, 'DisassemblyTime': disassemblyTime,
'eventType': eventTypeId, 'EventType': eventTypeId,
'customer': customerId, 'customer': customerId,
'address': GeoPoint(address.latitude, address.longitude), 'Address': GeoPoint(address.latitude, address.longitude),
'workforce': workforce,
}; };
} }
} }

View File

@ -0,0 +1,105 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../models/event_model.dart';
class EventProvider with ChangeNotifier {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
List<EventModel> _events = [];
bool _isLoading = false;
List<EventModel> get events => _events;
bool get isLoading => _isLoading;
// Récupérer les événements pour un utilisateur spécifique
Future<void> loadUserEvents(String userId) async {
_isLoading = true;
notifyListeners();
try {
print('Loading events for user: $userId');
// Récupérer uniquement les événements où l'utilisateur est dans la workforce
final eventsSnapshot = await _firestore
.collection('events')
.where('workforce', arrayContains: userId)
.get();
print('Found ${eventsSnapshot.docs.length} events for user');
_events = eventsSnapshot.docs.map((doc) {
print('Event data: ${doc.data()}');
return EventModel.fromMap(doc.data(), doc.id);
}).toList();
print('Parsed ${_events.length} events');
_isLoading = false;
notifyListeners();
} catch (e) {
print('Error loading events: $e');
_isLoading = false;
notifyListeners();
rethrow;
}
}
// Récupérer un événement spécifique
Future<EventModel?> getEvent(String eventId) async {
try {
final doc = await _firestore.collection('events').doc(eventId).get();
if (doc.exists) {
return EventModel.fromMap(doc.data()!, doc.id);
}
return null;
} catch (e) {
print('Error getting event: $e');
rethrow;
}
}
// Ajouter un nouvel événement
Future<void> addEvent(EventModel event) async {
try {
final docRef = await _firestore.collection('events').add(event.toMap());
final newEvent = EventModel.fromMap(event.toMap(), docRef.id);
_events.add(newEvent);
notifyListeners();
} catch (e) {
print('Error adding event: $e');
rethrow;
}
}
// Mettre à jour un événement
Future<void> updateEvent(EventModel event) async {
try {
await _firestore.collection('events').doc(event.id).update(event.toMap());
final index = _events.indexWhere((e) => e.id == event.id);
if (index != -1) {
_events[index] = event;
notifyListeners();
}
} catch (e) {
print('Error updating event: $e');
rethrow;
}
}
// Supprimer un événement
Future<void> deleteEvent(String eventId) async {
try {
await _firestore.collection('events').doc(eventId).delete();
_events.removeWhere((event) => event.id == eventId);
notifyListeners();
} catch (e) {
print('Error deleting event: $e');
rethrow;
}
}
// Vider la liste des événements
void clearEvents() {
_events = [];
notifyListeners();
}
}

View File

@ -1,14 +1,16 @@
import 'package:em2rp/providers/local_user_provider.dart'; import 'package:em2rp/providers/local_user_provider.dart';
import 'package:em2rp/providers/event_provider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:em2rp/widgets/custom_app_bar.dart'; import 'package:em2rp/widgets/custom_app_bar.dart';
import 'package:em2rp/views/widgets/nav/main_drawer.dart'; import 'package:em2rp/views/widgets/nav/main_drawer.dart';
import 'package:provider/provider.dart'; // Import Provider import 'package:provider/provider.dart';
import 'package:em2rp/utils/colors.dart'; import 'package:em2rp/utils/colors.dart';
import 'package:table_calendar/table_calendar.dart'; import 'package:table_calendar/table_calendar.dart';
import 'package:em2rp/models/event_model.dart'; import 'package:em2rp/models/event_model.dart';
import 'package:em2rp/widgets/event_details.dart'; import 'package:em2rp/widgets/event_details.dart';
import 'package:latlong2/latlong.dart'; import 'package:latlong2/latlong.dart';
import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/date_symbol_data_local.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class CalendarPage extends StatefulWidget { class CalendarPage extends StatefulWidget {
const CalendarPage({Key? key}) : super(key: key); const CalendarPage({Key? key}) : super(key: key);
@ -27,37 +29,19 @@ class _CalendarPageState extends State<CalendarPage> {
void initState() { void initState() {
super.initState(); super.initState();
initializeDateFormatting('fr_FR', null); initializeDateFormatting('fr_FR', null);
Future.microtask(() => _loadEvents());
} }
// Événements de test Future<void> _loadEvents() async {
final List<EventModel> _testEvents = [ final localAuthProvider =
EventModel( Provider.of<LocalUserProvider>(context, listen: false);
id: '1', final eventProvider = Provider.of<EventProvider>(context, listen: false);
name: 'Bal a Grammond', final userId = localAuthProvider.uid;
description: 'Lorem Ipsum',
startDateTime: DateTime(2025, 3, 28, 12, 30), if (userId != null) {
endDateTime: DateTime(2025, 3, 28, 23, 30), await eventProvider.loadUserEvents(userId);
price: 950.34, }
installationTime: 3, }
disassemblyTime: 2,
eventTypeId: '/eventTypes/Bal',
customerId: '/customers/DnjJ1HOPBLqEeExs0nDl',
address: const LatLng(45.566521035268224, 4.439601075086365),
),
EventModel(
id: '2',
name: 'Mariage à Lyon',
description: 'Cérémonie et réception',
startDateTime: DateTime(2025, 3, 28, 15, 0),
endDateTime: DateTime(2025, 3, 29, 4, 0),
price: 2500.00,
installationTime: 4,
disassemblyTime: 3,
eventTypeId: '/eventTypes/Mariage',
customerId: '/customers/Test123',
address: const LatLng(45.7578137, 4.8320114),
),
];
void _changeWeek(int delta) { void _changeWeek(int delta) {
setState(() { setState(() {
@ -68,8 +52,17 @@ class _CalendarPageState extends State<CalendarPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localAuthProvider = Provider.of<LocalUserProvider>(context); final localAuthProvider = Provider.of<LocalUserProvider>(context);
final eventProvider = Provider.of<EventProvider>(context);
final isMobile = MediaQuery.of(context).size.width < 600; final isMobile = MediaQuery.of(context).size.width < 600;
if (eventProvider.isLoading) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
return Scaffold( return Scaffold(
appBar: const CustomAppBar( appBar: const CustomAppBar(
title: 'Calendrier', title: 'Calendrier',
@ -452,7 +445,7 @@ class _CalendarPageState extends State<CalendarPage> {
// Préparer les événements par jour (en tenant compte des multi-jours) // Préparer les événements par jour (en tenant compte des multi-jours)
List<List<_PositionedEvent>> eventsByDay = List.generate(7, (i) => []); List<List<_PositionedEvent>> eventsByDay = List.generate(7, (i) => []);
for (final event in _testEvents) { for (final event in Provider.of<EventProvider>(context).events) {
// Pour chaque jour de la semaine // Pour chaque jour de la semaine
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
final day = weekStart.add(Duration(days: i)); final day = weekStart.add(Duration(days: i));
@ -735,7 +728,7 @@ class _CalendarPageState extends State<CalendarPage> {
final dayStart = DateTime(day.year, day.month, day.day, 0, 0); final dayStart = DateTime(day.year, day.month, day.day, 0, 0);
final dayEnd = DateTime(day.year, day.month, day.day, 23, 59, 59); final dayEnd = DateTime(day.year, day.month, day.day, 23, 59, 59);
return _testEvents.where((event) { return Provider.of<EventProvider>(context).events.where((event) {
return !(event.endDateTime.isBefore(dayStart) || return !(event.endDateTime.isBefore(dayStart) ||
event.startDateTime.isAfter(dayEnd)); event.startDateTime.isAfter(dayEnd));
}).toList(); }).toList();