203 lines
6.1 KiB
Dart
203 lines
6.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:table_calendar/table_calendar.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import '../../models/event_model.dart';
|
|
import '../../services/event_service.dart';
|
|
import '../../services/auth_service.dart';
|
|
import '../../services/club_service.dart';
|
|
import 'event_details_screen.dart';
|
|
|
|
class EventCalendarScreen extends StatefulWidget {
|
|
const EventCalendarScreen({super.key});
|
|
|
|
@override
|
|
State<EventCalendarScreen> createState() => _EventCalendarScreenState();
|
|
}
|
|
|
|
class _EventCalendarScreenState extends State<EventCalendarScreen> {
|
|
CalendarFormat _calendarFormat = CalendarFormat.month;
|
|
DateTime _focusedDay = DateTime.now();
|
|
DateTime? _selectedDay;
|
|
Map<DateTime, List<Event>> _events = {};
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadEvents();
|
|
}
|
|
|
|
Future<void> _loadEvents() async {
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
|
|
try {
|
|
final authService = Provider.of<AuthService>(context, listen: false);
|
|
final clubService = Provider.of<ClubService>(context, listen: false);
|
|
final eventService = Provider.of<EventService>(context, listen: false);
|
|
|
|
if (clubService.currentClub != null) {
|
|
eventService.initialize(authService.token!);
|
|
await eventService.fetchClubEvents();
|
|
|
|
// 이벤트를 날짜별로 그룹화
|
|
final Map<DateTime, List<Event>> eventMap = {};
|
|
|
|
for (final event in eventService.events) {
|
|
final date = DateTime(
|
|
event.startDate.year,
|
|
event.startDate.month,
|
|
event.startDate.day,
|
|
);
|
|
|
|
if (eventMap[date] == null) {
|
|
eventMap[date] = [];
|
|
}
|
|
|
|
eventMap[date]!.add(event);
|
|
}
|
|
|
|
setState(() {
|
|
_events = eventMap;
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
|
|
if (mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('이벤트를 불러오는데 실패했습니다: $e')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
List<Event> _getEventsForDay(DateTime day) {
|
|
final normalizedDay = DateTime(day.year, day.month, day.day);
|
|
return _events[normalizedDay] ?? [];
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('이벤트 캘린더'),
|
|
actions: [
|
|
IconButton(
|
|
icon: const Icon(Icons.refresh),
|
|
onPressed: _loadEvents,
|
|
),
|
|
],
|
|
),
|
|
body: _isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: Column(
|
|
children: [
|
|
TableCalendar(
|
|
firstDay: DateTime.now().subtract(const Duration(days: 365)),
|
|
lastDay: DateTime.now().add(const Duration(days: 365)),
|
|
focusedDay: _focusedDay,
|
|
calendarFormat: _calendarFormat,
|
|
selectedDayPredicate: (day) {
|
|
return isSameDay(_selectedDay, day);
|
|
},
|
|
onDaySelected: (selectedDay, focusedDay) {
|
|
setState(() {
|
|
_selectedDay = selectedDay;
|
|
_focusedDay = focusedDay;
|
|
});
|
|
},
|
|
onFormatChanged: (format) {
|
|
setState(() {
|
|
_calendarFormat = format;
|
|
});
|
|
},
|
|
onPageChanged: (focusedDay) {
|
|
_focusedDay = focusedDay;
|
|
},
|
|
eventLoader: _getEventsForDay,
|
|
calendarStyle: const CalendarStyle(
|
|
markersMaxCount: 3,
|
|
markerDecoration: BoxDecoration(
|
|
color: Colors.blue,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
headerStyle: const HeaderStyle(
|
|
formatButtonShowsNext: false,
|
|
titleCentered: true,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Expanded(
|
|
child: _selectedDay == null
|
|
? const Center(child: Text('날짜를 선택하세요'))
|
|
: _buildEventList(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildEventList() {
|
|
final events = _getEventsForDay(_selectedDay!);
|
|
final dateFormat = DateFormat('HH:mm');
|
|
|
|
if (events.isEmpty) {
|
|
return const Center(child: Text('선택한 날짜에 이벤트가 없습니다'));
|
|
}
|
|
|
|
return ListView.builder(
|
|
itemCount: events.length,
|
|
itemBuilder: (context, index) {
|
|
final event = events[index];
|
|
return Card(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
|
child: ListTile(
|
|
leading: Container(
|
|
width: 48,
|
|
height: 48,
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue[100],
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: const Icon(Icons.event, color: Colors.blue),
|
|
),
|
|
title: Text(
|
|
event.title,
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
subtitle: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(dateFormat.format(event.startDate)),
|
|
if (event.location != null) Text(event.location!),
|
|
],
|
|
),
|
|
onTap: () => _navigateToEventDetails(event),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _navigateToEventDetails(Event event) {
|
|
Navigator.of(context).push(
|
|
MaterialPageRoute(
|
|
builder: (context) => EventDetailsScreen(event: event),
|
|
),
|
|
).then((result) {
|
|
if (result == true) {
|
|
// 이벤트가 수정되었으면 목록 새로고침
|
|
_loadEvents();
|
|
}
|
|
});
|
|
}
|
|
}
|