tdd 진행
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user