import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import '../models/schedule_item.dart'; import '../services/schedule_service.dart'; class CalendarWidget extends StatefulWidget { const CalendarWidget({super.key}); @override State createState() => _CalendarWidgetState(); } class _CalendarWidgetState extends State { List _schedules = []; @override void initState() { super.initState(); _loadSchedules(); } Future _loadSchedules() async { try { final schedules = await Provider.of(context, listen: false) .fetchMonthlySchedules(); if (mounted) { setState(() { _schedules = schedules; }); } } catch (e) { debugPrint('Error loading schedules: $e'); } } bool _hasScheduleOn(DateTime date) { final checkDate = DateTime(date.year, date.month, date.day); return _schedules.any((s) { final start = DateTime(s.startDate.year, s.startDate.month, s.startDate.day); final end = DateTime(s.endDate.year, s.endDate.month, s.endDate.day); return (checkDate.isAtSameMomentAs(start) || checkDate.isAfter(start)) && (checkDate.isAtSameMomentAs(end) || checkDate.isBefore(end)); }); } @override Widget build(BuildContext context) { final now = DateTime.now(); final firstDayOfMonth = DateTime(now.year, now.month, 1); final lastDayOfMonth = DateTime(now.year, now.month + 1, 0); final daysInMonth = lastDayOfMonth.day; final startingWeekday = firstDayOfMonth.weekday; // Mon=1, Sun=7 int offset = startingWeekday % 7; return Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Theme.of(context).cardTheme.color, borderRadius: BorderRadius.circular(16), ), child: Column( children: [ // Header Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( DateFormat('yyyy년 M월').format(now), style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, color: Colors.white, fontSize: 20, ), ), const Icon(Icons.calendar_today, color: Colors.white54, size: 20), ], ), ), const SizedBox(height: 8), // Days Header Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: ['일', '월', '화', '수', '목', '금', '토'].asMap().entries.map((entry) { final isSunday = entry.key == 0; return Expanded( child: Center( child: Text( entry.value, style: TextStyle( color: isSunday ? Colors.redAccent : Colors.white54, fontWeight: FontWeight.bold, fontSize: 14, ), ), ), ); }).toList(), ), const SizedBox(height: 4), // Days Grid Expanded( child: Column( children: List.generate(6, (row) { return Expanded( child: Row( children: List.generate(7, (col) { final index = row * 7 + col; final dayNumber = index - offset + 1; final isSunday = col == 0; if (dayNumber < 1 || dayNumber > daysInMonth) { return const Expanded(child: SizedBox.shrink()); } final dayDate = DateTime(now.year, now.month, dayNumber); final isToday = dayNumber == now.day; final hasSchedule = _hasScheduleOn(dayDate); return Expanded( child: Container( margin: const EdgeInsets.all(1), decoration: isToday ? BoxDecoration( border: Border.all( color: Theme.of(context).colorScheme.primary, width: 2, ), shape: BoxShape.circle, ) : null, child: Stack( alignment: Alignment.center, children: [ Center( child: FittedBox( fit: BoxFit.scaleDown, child: Text( '$dayNumber', style: TextStyle( color: isToday ? Theme.of(context).colorScheme.primary : (isSunday ? Colors.redAccent : Colors.white), fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ), if (hasSchedule) // Show indicator even if it's today Positioned( bottom: 2, child: Container( width: 14, height: 4, decoration: BoxDecoration( color: Colors.yellowAccent, borderRadius: BorderRadius.circular(2), ), ), ), ], ), ), ); }), ), ); }), ), ), ], ), ); } }