Refacto et clean
This commit is contained in:
		
							
								
								
									
										238
									
								
								em2rp/lib/views/widgets/calendar_widgets/month_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								em2rp/lib/views/widgets/calendar_widgets/month_view.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:table_calendar/table_calendar.dart'; | ||||
| import 'package:em2rp/utils/colors.dart'; | ||||
| import 'package:em2rp/models/event_model.dart'; | ||||
| import 'package:em2rp/utils/calendar_utils.dart'; | ||||
|  | ||||
| class MonthView extends StatelessWidget { | ||||
|   final DateTime focusedDay; | ||||
|   final DateTime? selectedDay; | ||||
|   final CalendarFormat calendarFormat; | ||||
|   final Function(DateTime, DateTime) onDaySelected; | ||||
|   final Function(CalendarFormat) onFormatChanged; | ||||
|   final Function(DateTime) onPageChanged; | ||||
|   final List<EventModel> events; | ||||
|   final Function(EventModel) onEventSelected; | ||||
|  | ||||
|   const MonthView({ | ||||
|     super.key, | ||||
|     required this.focusedDay, | ||||
|     required this.selectedDay, | ||||
|     required this.calendarFormat, | ||||
|     required this.onDaySelected, | ||||
|     required this.onFormatChanged, | ||||
|     required this.onPageChanged, | ||||
|     required this.events, | ||||
|     required this.onEventSelected, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return LayoutBuilder( | ||||
|       builder: (context, constraints) { | ||||
|         final rowHeight = (constraints.maxHeight - 100) / 6; | ||||
|  | ||||
|         return Container( | ||||
|           height: constraints.maxHeight, | ||||
|           padding: const EdgeInsets.all(8), | ||||
|           child: TableCalendar( | ||||
|             firstDay: DateTime.utc(2020, 1, 1), | ||||
|             lastDay: DateTime.utc(2030, 12, 31), | ||||
|             focusedDay: focusedDay, | ||||
|             calendarFormat: calendarFormat, | ||||
|             startingDayOfWeek: StartingDayOfWeek.monday, | ||||
|             locale: 'fr_FR', | ||||
|             availableCalendarFormats: const { | ||||
|               CalendarFormat.month: 'Mois', | ||||
|               CalendarFormat.week: 'Semaine', | ||||
|             }, | ||||
|             selectedDayPredicate: (day) => isSameDay(selectedDay, day), | ||||
|             onDaySelected: onDaySelected, | ||||
|             onFormatChanged: onFormatChanged, | ||||
|             onPageChanged: onPageChanged, | ||||
|             calendarStyle: _buildCalendarStyle(), | ||||
|             rowHeight: rowHeight, | ||||
|             headerStyle: _buildHeaderStyle(), | ||||
|             calendarBuilders: _buildCalendarBuilders(), | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   CalendarStyle _buildCalendarStyle() { | ||||
|     return CalendarStyle( | ||||
|       defaultDecoration: BoxDecoration( | ||||
|         border: Border.all(color: Colors.grey.shade300), | ||||
|         borderRadius: BorderRadius.circular(4), | ||||
|       ), | ||||
|       selectedDecoration: BoxDecoration( | ||||
|         color: AppColors.rouge, | ||||
|         border: Border.all(color: AppColors.rouge), | ||||
|         borderRadius: BorderRadius.circular(4), | ||||
|       ), | ||||
|       todayDecoration: BoxDecoration( | ||||
|         color: AppColors.rouge.withAlpha(26), | ||||
|         border: Border.all(color: AppColors.rouge), | ||||
|         borderRadius: BorderRadius.circular(4), | ||||
|       ), | ||||
|       outsideDecoration: BoxDecoration( | ||||
|         border: Border.all(color: Colors.grey.shade300), | ||||
|         borderRadius: BorderRadius.circular(4), | ||||
|       ), | ||||
|       outsideDaysVisible: false, | ||||
|       cellMargin: EdgeInsets.zero, | ||||
|       cellPadding: EdgeInsets.zero, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   HeaderStyle _buildHeaderStyle() { | ||||
|     return HeaderStyle( | ||||
|       formatButtonVisible: true, | ||||
|       titleCentered: true, | ||||
|       formatButtonShowsNext: false, | ||||
|       formatButtonDecoration: BoxDecoration( | ||||
|         color: AppColors.rouge, | ||||
|         borderRadius: BorderRadius.circular(16), | ||||
|       ), | ||||
|       formatButtonTextStyle: const TextStyle(color: Colors.white), | ||||
|       leftChevronIcon: const Icon(Icons.chevron_left, color: AppColors.rouge), | ||||
|       rightChevronIcon: const Icon(Icons.chevron_right, color: AppColors.rouge), | ||||
|       headerPadding: const EdgeInsets.symmetric(vertical: 8), | ||||
|       titleTextStyle: const TextStyle( | ||||
|         fontSize: 18, | ||||
|         fontWeight: FontWeight.bold, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   CalendarBuilders _buildCalendarBuilders() { | ||||
|     return CalendarBuilders( | ||||
|       dowBuilder: (context, day) { | ||||
|         return Center( | ||||
|           child: Text( | ||||
|             CalendarUtils.getShortDayName(day.weekday), | ||||
|             style: const TextStyle( | ||||
|               fontWeight: FontWeight.bold, | ||||
|             ), | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|       defaultBuilder: (context, day, focusedDay) { | ||||
|         return _buildDayCell(day, false); | ||||
|       }, | ||||
|       selectedBuilder: (context, day, focusedDay) { | ||||
|         return _buildDayCell(day, true); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildDayCell(DateTime day, bool isSelected) { | ||||
|     final dayEvents = CalendarUtils.getEventsForDay(day, events); | ||||
|     final textColor = isSelected ? Colors.white : null; | ||||
|     final badgeColor = isSelected ? Colors.white : AppColors.rouge; | ||||
|     final badgeTextColor = isSelected ? AppColors.rouge : Colors.white; | ||||
|  | ||||
|     return Container( | ||||
|       margin: const EdgeInsets.all(4), | ||||
|       decoration: BoxDecoration( | ||||
|         color: isSelected ? AppColors.rouge : null, | ||||
|         border: Border.all( | ||||
|           color: isSelected ? AppColors.rouge : Colors.grey.shade300, | ||||
|         ), | ||||
|         borderRadius: BorderRadius.circular(4), | ||||
|       ), | ||||
|       child: Stack( | ||||
|         children: [ | ||||
|           Positioned( | ||||
|             top: 4, | ||||
|             left: 4, | ||||
|             child: Text( | ||||
|               day.day.toString(), | ||||
|               style: TextStyle(color: textColor), | ||||
|             ), | ||||
|           ), | ||||
|           if (dayEvents.isNotEmpty) | ||||
|             Positioned( | ||||
|               top: 4, | ||||
|               right: 4, | ||||
|               child: Container( | ||||
|                 padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), | ||||
|                 decoration: BoxDecoration( | ||||
|                   color: badgeColor, | ||||
|                   borderRadius: BorderRadius.circular(10), | ||||
|                 ), | ||||
|                 child: Text( | ||||
|                   dayEvents.length.toString(), | ||||
|                   style: TextStyle( | ||||
|                     color: badgeTextColor, | ||||
|                     fontSize: 12, | ||||
|                     fontWeight: FontWeight.bold, | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           if (dayEvents.isNotEmpty) | ||||
|             Positioned( | ||||
|               bottom: 2, | ||||
|               left: 2, | ||||
|               right: 2, | ||||
|               top: 28, | ||||
|               child: SingleChildScrollView( | ||||
|                 child: Column( | ||||
|                   crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                   children: dayEvents | ||||
|                       .map((event) => _buildEventItem(event, isSelected, day)) | ||||
|                       .toList(), | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildEventItem( | ||||
|       EventModel event, bool isSelected, DateTime currentDay) { | ||||
|     return GestureDetector( | ||||
|       onTap: () { | ||||
|         onDaySelected(currentDay, currentDay); | ||||
|         onEventSelected(event); | ||||
|       }, | ||||
|       child: Container( | ||||
|         margin: const EdgeInsets.only(bottom: 2), | ||||
|         padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), | ||||
|         decoration: BoxDecoration( | ||||
|           color: isSelected | ||||
|               ? Colors.white.withAlpha(51) | ||||
|               : AppColors.rouge.withAlpha(26), | ||||
|           borderRadius: BorderRadius.circular(4), | ||||
|         ), | ||||
|         child: Column( | ||||
|           crossAxisAlignment: CrossAxisAlignment.start, | ||||
|           children: [ | ||||
|             Text( | ||||
|               event.name, | ||||
|               style: TextStyle( | ||||
|                 fontSize: 12, | ||||
|                 color: isSelected ? Colors.white : AppColors.rouge, | ||||
|                 fontWeight: FontWeight.bold, | ||||
|               ), | ||||
|               maxLines: 1, | ||||
|               overflow: TextOverflow.ellipsis, | ||||
|             ), | ||||
|             if (CalendarUtils.isMultiDayEvent(event)) | ||||
|               Text( | ||||
|                 'Jour ${CalendarUtils.calculateDayNumber(event.startDateTime, event.startDateTime)}/${CalendarUtils.calculateTotalDays(event)}', | ||||
|                 style: TextStyle( | ||||
|                   fontSize: 10, | ||||
|                   color: isSelected ? Colors.white : AppColors.rouge, | ||||
|                 ), | ||||
|                 maxLines: 1, | ||||
|               ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										383
									
								
								em2rp/lib/views/widgets/calendar_widgets/week_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										383
									
								
								em2rp/lib/views/widgets/calendar_widgets/week_view.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,383 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:em2rp/utils/colors.dart'; | ||||
| import 'package:em2rp/models/event_model.dart'; | ||||
| import 'package:em2rp/utils/calendar_utils.dart'; | ||||
|  | ||||
| class WeekView extends StatelessWidget { | ||||
|   final DateTime focusedDay; | ||||
|   final List<EventModel> events; | ||||
|   final Function(int) onWeekChange; | ||||
|   final Function(EventModel) onEventSelected; | ||||
|   final Function() onSwitchToMonth; | ||||
|  | ||||
|   const WeekView({ | ||||
|     super.key, | ||||
|     required this.focusedDay, | ||||
|     required this.events, | ||||
|     required this.onWeekChange, | ||||
|     required this.onEventSelected, | ||||
|     required this.onSwitchToMonth, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final weekStart = | ||||
|         focusedDay.subtract(Duration(days: focusedDay.weekday - 1)); | ||||
|     final weekEnd = weekStart.add(const Duration(days: 6)); | ||||
|  | ||||
|     return Column( | ||||
|       children: [ | ||||
|         _buildWeekHeader(weekStart, weekEnd), | ||||
|         Expanded( | ||||
|           child: LayoutBuilder( | ||||
|             builder: (context, constraints) { | ||||
|               final availableHeight = constraints.maxHeight - 80; | ||||
|               final hourHeight = availableHeight / 24; | ||||
|               final dayWidth = (constraints.maxWidth - 50) / 7; | ||||
|  | ||||
|               return SingleChildScrollView( | ||||
|                 child: SizedBox( | ||||
|                   height: 24 * hourHeight, | ||||
|                   child: Row( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     children: [ | ||||
|                       _buildHourColumn(hourHeight), | ||||
|                       Expanded( | ||||
|                         child: _buildWeekGrid( | ||||
|                           weekStart, | ||||
|                           hourHeight, | ||||
|                           dayWidth, | ||||
|                           constraints, | ||||
|                         ), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|               ); | ||||
|             }, | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildWeekHeader(DateTime weekStart, DateTime weekEnd) { | ||||
|     return Column( | ||||
|       children: [ | ||||
|         Padding( | ||||
|           padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), | ||||
|           child: Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               IconButton( | ||||
|                 icon: const Icon(Icons.chevron_left), | ||||
|                 onPressed: () => onWeekChange(-1), | ||||
|               ), | ||||
|               Text( | ||||
|                 CalendarUtils.getMonthYearString(weekStart, weekEnd), | ||||
|                 style: | ||||
|                     const TextStyle(fontWeight: FontWeight.bold, fontSize: 18), | ||||
|               ), | ||||
|               Row( | ||||
|                 children: [ | ||||
|                   TextButton( | ||||
|                     onPressed: onSwitchToMonth, | ||||
|                     style: TextButton.styleFrom( | ||||
|                       backgroundColor: AppColors.rouge, | ||||
|                       foregroundColor: Colors.white, | ||||
|                       shape: RoundedRectangleBorder( | ||||
|                         borderRadius: BorderRadius.circular(16), | ||||
|                       ), | ||||
|                       padding: const EdgeInsets.symmetric( | ||||
|                           horizontal: 12, vertical: 8), | ||||
|                     ), | ||||
|                     child: const Text('Semaine'), | ||||
|                   ), | ||||
|                   IconButton( | ||||
|                     icon: const Icon(Icons.chevron_right), | ||||
|                     onPressed: () => onWeekChange(1), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|         _buildDaysHeader(weekStart), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildDaysHeader(DateTime weekStart) { | ||||
|     return SizedBox( | ||||
|       height: 40, | ||||
|       child: Row( | ||||
|         children: [ | ||||
|           Container( | ||||
|             width: 50, | ||||
|             color: Colors.transparent, | ||||
|           ), | ||||
|           ...List.generate(7, (index) { | ||||
|             final day = weekStart.add(Duration(days: index)); | ||||
|             return Expanded( | ||||
|               child: Container( | ||||
|                 decoration: BoxDecoration( | ||||
|                   border: Border( | ||||
|                     right: BorderSide( | ||||
|                       color: | ||||
|                           index < 6 ? Colors.grey.shade300 : Colors.transparent, | ||||
|                       width: 1, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|                 child: Stack( | ||||
|                   children: [ | ||||
|                     Center( | ||||
|                       child: Column( | ||||
|                         mainAxisAlignment: MainAxisAlignment.center, | ||||
|                         children: [ | ||||
|                           Text( | ||||
|                             CalendarUtils.getShortDayName(day.weekday), | ||||
|                             style: const TextStyle(fontWeight: FontWeight.bold), | ||||
|                           ), | ||||
|                           Text( | ||||
|                             '${day.day}', | ||||
|                             style: const TextStyle(fontSize: 13), | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                     if (CalendarUtils.getEventsForDay(day, events).isNotEmpty) | ||||
|                       Positioned( | ||||
|                         top: 4, | ||||
|                         right: 4, | ||||
|                         child: Container( | ||||
|                           padding: const EdgeInsets.symmetric( | ||||
|                               horizontal: 6, vertical: 2), | ||||
|                           decoration: BoxDecoration( | ||||
|                             color: AppColors.rouge, | ||||
|                             borderRadius: BorderRadius.circular(10), | ||||
|                           ), | ||||
|                           child: Text( | ||||
|                             CalendarUtils.getEventsForDay(day, events) | ||||
|                                 .length | ||||
|                                 .toString(), | ||||
|                             style: const TextStyle( | ||||
|                               color: Colors.white, | ||||
|                               fontSize: 10, | ||||
|                               fontWeight: FontWeight.bold, | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ); | ||||
|           }), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildHourColumn(double hourHeight) { | ||||
|     return Column( | ||||
|       children: List.generate(24, (index) { | ||||
|         return Container( | ||||
|           width: 50, | ||||
|           height: hourHeight, | ||||
|           alignment: Alignment.topRight, | ||||
|           padding: const EdgeInsets.only(right: 4), | ||||
|           child: Text( | ||||
|             '${index.toString().padLeft(2, '0')}:00', | ||||
|             style: TextStyle( | ||||
|               color: Colors.grey.shade600, | ||||
|               fontSize: 12, | ||||
|             ), | ||||
|           ), | ||||
|         ); | ||||
|       }), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildWeekGrid( | ||||
|     DateTime weekStart, | ||||
|     double hourHeight, | ||||
|     double dayWidth, | ||||
|     BoxConstraints constraints, | ||||
|   ) { | ||||
|     final eventsByDay = _prepareEventsByDay(weekStart); | ||||
|     final eventsWithColumnsByDay = _assignColumnsToEvents(eventsByDay); | ||||
|  | ||||
|     return Stack( | ||||
|       children: [ | ||||
|         // Lignes horizontales | ||||
|         Column( | ||||
|           children: List.generate(24, (index) { | ||||
|             return Container( | ||||
|               height: hourHeight, | ||||
|               decoration: BoxDecoration( | ||||
|                 border: Border( | ||||
|                   bottom: BorderSide( | ||||
|                     color: Colors.grey.shade300, | ||||
|                     width: 0.5, | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|             ); | ||||
|           }), | ||||
|         ), | ||||
|         // Bordures verticales entre jours | ||||
|         Positioned.fill( | ||||
|           child: Row( | ||||
|             children: List.generate(7, (i) { | ||||
|               return Container( | ||||
|                 width: dayWidth, | ||||
|                 decoration: BoxDecoration( | ||||
|                   border: Border( | ||||
|                     right: BorderSide( | ||||
|                       color: i < 6 ? Colors.grey.shade300 : Colors.transparent, | ||||
|                       width: 1, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ); | ||||
|             }), | ||||
|           ), | ||||
|         ), | ||||
|         // Événements | ||||
|         ...List.generate(7, (dayIdx) { | ||||
|           final dayEvents = eventsWithColumnsByDay[dayIdx]; | ||||
|           return Stack( | ||||
|             children: dayEvents.map((e) { | ||||
|               final startHour = e.start.hour + e.start.minute / 60; | ||||
|               final endHour = e.end.hour + e.end.minute / 60; | ||||
|               final duration = endHour - startHour; | ||||
|               final width = dayWidth / e.totalColumns; | ||||
|  | ||||
|               return Positioned( | ||||
|                 left: dayIdx * dayWidth + e.column * width, | ||||
|                 top: startHour * hourHeight, | ||||
|                 width: width, | ||||
|                 height: duration * hourHeight, | ||||
|                 child: GestureDetector( | ||||
|                   onTap: () => onEventSelected(e.event), | ||||
|                   child: Container( | ||||
|                     margin: const EdgeInsets.all(2), | ||||
|                     padding: const EdgeInsets.all(4), | ||||
|                     decoration: BoxDecoration( | ||||
|                       color: AppColors.rouge.withAlpha(26), | ||||
|                       border: Border.all(color: AppColors.rouge), | ||||
|                       borderRadius: BorderRadius.circular(4), | ||||
|                     ), | ||||
|                     child: Column( | ||||
|                       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                       children: [ | ||||
|                         Text( | ||||
|                           e.event.name, | ||||
|                           style: const TextStyle( | ||||
|                             color: AppColors.rouge, | ||||
|                             fontSize: 12, | ||||
|                             fontWeight: FontWeight.bold, | ||||
|                           ), | ||||
|                           maxLines: 1, | ||||
|                           overflow: TextOverflow.ellipsis, | ||||
|                         ), | ||||
|                         if (CalendarUtils.isMultiDayEvent(e.event)) | ||||
|                           Text( | ||||
|                             'Jour ${CalendarUtils.calculateDayNumber(e.event.startDateTime, weekStart.add(Duration(days: dayIdx)))}/${CalendarUtils.calculateTotalDays(e.event)}', | ||||
|                             style: const TextStyle( | ||||
|                               color: AppColors.rouge, | ||||
|                               fontSize: 10, | ||||
|                             ), | ||||
|                             maxLines: 1, | ||||
|                           ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ); | ||||
|             }).toList(), | ||||
|           ); | ||||
|         }), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   List<List<_PositionedEvent>> _prepareEventsByDay(DateTime weekStart) { | ||||
|     List<List<_PositionedEvent>> eventsByDay = List.generate(7, (i) => []); | ||||
|  | ||||
|     for (final event in events) { | ||||
|       for (int i = 0; i < 7; i++) { | ||||
|         final day = weekStart.add(Duration(days: i)); | ||||
|         final dayStart = DateTime(day.year, day.month, day.day, 0, 0); | ||||
|         final dayEnd = DateTime(day.year, day.month, day.day, 23, 59, 59); | ||||
|  | ||||
|         if (!(event.endDateTime.isBefore(dayStart) || | ||||
|             event.startDateTime.isAfter(dayEnd))) { | ||||
|           final start = event.startDateTime.isBefore(dayStart) | ||||
|               ? dayStart | ||||
|               : event.startDateTime; | ||||
|           final end = | ||||
|               event.endDateTime.isAfter(dayEnd) ? dayEnd : event.endDateTime; | ||||
|           eventsByDay[i].add(_PositionedEvent(event, start, end)); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return eventsByDay; | ||||
|   } | ||||
|  | ||||
|   List<List<_PositionedEventWithColumn>> _assignColumnsToEvents( | ||||
|       List<List<_PositionedEvent>> eventsByDay) { | ||||
|     return eventsByDay.map((dayEvents) { | ||||
|       dayEvents.sort((a, b) => a.start.compareTo(b.start)); | ||||
|       List<_PositionedEventWithColumn> result = []; | ||||
|       List<List<_PositionedEventWithColumn>> columns = []; | ||||
|  | ||||
|       for (final e in dayEvents) { | ||||
|         bool placed = false; | ||||
|         for (int col = 0; col < columns.length; col++) { | ||||
|           if (columns[col].isEmpty || !_overlap(columns[col].last, e)) { | ||||
|             columns[col].add( | ||||
|                 _PositionedEventWithColumn(e.event, e.start, e.end, col, 0)); | ||||
|             placed = true; | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|         if (!placed) { | ||||
|           columns.add([ | ||||
|             _PositionedEventWithColumn( | ||||
|                 e.event, e.start, e.end, columns.length, 0) | ||||
|           ]); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       int totalCols = columns.length; | ||||
|       for (final col in columns) { | ||||
|         for (final e in col) { | ||||
|           result.add(_PositionedEventWithColumn( | ||||
|               e.event, e.start, e.end, e.column, totalCols)); | ||||
|         } | ||||
|       } | ||||
|       return result; | ||||
|     }).toList(); | ||||
|   } | ||||
|  | ||||
|   bool _overlap(_PositionedEvent a, _PositionedEvent b) { | ||||
|     return a.end.isAfter(b.start) && a.start.isBefore(b.end); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _PositionedEvent { | ||||
|   final EventModel event; | ||||
|   final DateTime start; | ||||
|   final DateTime end; | ||||
|   _PositionedEvent(this.event, this.start, this.end); | ||||
| } | ||||
|  | ||||
| class _PositionedEventWithColumn extends _PositionedEvent { | ||||
|   final int column; | ||||
|   final int totalColumns; | ||||
|   _PositionedEventWithColumn( | ||||
|       super.event, super.start, super.end, this.column, this.totalColumns); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user