import 'package:flutter/material.dart'; import '../../../core/theme/app_theme.dart'; import '../../../core/widgets/glass_container.dart'; /// Compact Interactive Monthly Calendar Grid with event markers and event count dots. class MonthCalendarWidget extends StatelessWidget { final DateTime currentMonth; final DateTime? selectedDate; final List events; final Function(DateTime) onDateSelected; final Function(DateTime) onMonthChanged; const MonthCalendarWidget({ super.key, required this.currentMonth, required this.selectedDate, required this.events, required this.onDateSelected, required this.onMonthChanged, }); static const List weekDays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; static const List monthNames = [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ]; DateTime _parseEventDate(dynamic raw) { if (raw == null) return DateTime(1970); final str = raw.toString(); try { if (str.contains('.')) { final parts = str.split('.'); if (parts.length >= 3) { return DateTime(int.parse(parts[2]), int.parse(parts[1]), int.parse(parts[0])); } } return DateTime.parse(str); } catch (_) { return DateTime(1970); } } List _getEventsForDate(DateTime date) { return events.where((e) { final dt = _parseEventDate(e['eventDate'] ?? e['EventDate']); return dt.year == date.year && dt.month == date.month && dt.day == date.day; }).toList(); } @override Widget build(BuildContext context) { final firstDayOfMonth = DateTime(currentMonth.year, currentMonth.month, 1); final daysInMonth = DateTime(currentMonth.year, currentMonth.month + 1, 0).day; // ISO weekday: Monday = 1, Sunday = 7 final firstWeekday = firstDayOfMonth.weekday; final leadingEmptyDays = firstWeekday - 1; final totalCells = ((leadingEmptyDays + daysInMonth) / 7).ceil() * 7; return Center( child: Container( child: GlassContainer( padding: const EdgeInsets.all(12), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Month Header Navigation Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( icon: Icon(Icons.chevron_left, color: AppTheme.accentCyan, size: 20), padding: EdgeInsets.zero, constraints: const BoxConstraints(), onPressed: () => onMonthChanged(DateTime(currentMonth.year, currentMonth.month - 1, 1)), ), Text( '${monthNames[currentMonth.month - 1]} ${currentMonth.year}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: AppTheme.textPrimary), ), IconButton( icon: Icon(Icons.chevron_right, color: AppTheme.accentCyan, size: 20), padding: EdgeInsets.zero, constraints: const BoxConstraints(), onPressed: () => onMonthChanged(DateTime(currentMonth.year, currentMonth.month + 1, 1)), ), ], ), const SizedBox(height: 6), // Weekday Labels Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: weekDays.map((w) => Expanded( child: Center( child: Text( w, style: TextStyle(color: AppTheme.textMuted, fontSize: 11, fontWeight: FontWeight.bold), ), ), )).toList(), ), const SizedBox(height: 4), // Days Grid GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: totalCells, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7, childAspectRatio: 2, ), itemBuilder: (context, index) { final dayNumber = index - leadingEmptyDays + 1; if (dayNumber < 1 || dayNumber > daysInMonth) { return const SizedBox(); } final cellDate = DateTime(currentMonth.year, currentMonth.month, dayNumber); final isSelected = selectedDate != null && selectedDate!.year == cellDate.year && selectedDate!.month == cellDate.month && selectedDate!.day == cellDate.day; final isToday = DateTime.now().year == cellDate.year && DateTime.now().month == cellDate.month && DateTime.now().day == cellDate.day; final dayEvents = _getEventsForDate(cellDate); final eventCount = dayEvents.length; return InkWell( onTap: () => onDateSelected(cellDate), borderRadius: BorderRadius.circular(6), child: Container( margin: const EdgeInsets.all(1.5), decoration: BoxDecoration( color: isSelected ? AppTheme.primaryEmerald.withValues(alpha: 0.3) : (isToday ? AppTheme.glassSurface : Colors.transparent), borderRadius: BorderRadius.circular(6), border: Border.all( color: isSelected ? AppTheme.primaryEmerald : (eventCount > 0 ? AppTheme.accentCyan.withValues(alpha: 0.6) : Colors.transparent), width: isSelected ? 1.5 : 1.0, ), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '$dayNumber', style: TextStyle( fontSize: 11.5, fontWeight: isSelected || isToday || eventCount > 0 ? FontWeight.bold : FontWeight.normal, color: isSelected ? AppTheme.primaryEmerald : (eventCount > 0 ? AppTheme.textPrimary : AppTheme.textSecondary), ), ), if (eventCount > 0) ...[ const SizedBox(height: 1), Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate( eventCount > 4 ? 4 : eventCount, (i) => Container( margin: const EdgeInsets.symmetric(horizontal: 1), width: 4, height: 4, decoration: BoxDecoration( color: AppTheme.accentCyan, shape: BoxShape.circle, ), ), ), ), ], ], ), ), ); }, ), ], ), ), ), ); } }