Files
bowlingManager/mobile/lib/services/event_service.dart
T
2025-08-09 03:09:17 +09:00

662 lines
17 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/api_config.dart';
import '../models/event_model.dart';
import '../models/participant_model.dart';
import '../models/score_model.dart';
import '../models/team_model.dart';
import './api_service.dart';
class EventService with ChangeNotifier {
List<Event> _events = [];
Event? _currentEvent;
List<Participant> _participants = [];
List<Score> _scores = [];
List<Team> _teams = [];
bool _isLoading = false;
String? _token;
ApiService _apiService;
String? _clubId;
// 기본 생성자
EventService() : _apiService = ApiService();
// 테스트용 생성자
EventService.forTest(this._apiService);
List<Event> get events => [..._events];
Event? get currentEvent => _currentEvent;
List<Participant> get participants => [..._participants];
List<Score> get scores => [..._scores];
List<Team> get teams => [..._teams];
bool get isLoading => _isLoading;
// 초기화 함수
Future<void> initialize(String token) async {
_token = token;
_apiService.setToken(token);
}
// 클럽 ID 설정
void setClubId(String clubId) {
_clubId = clubId;
notifyListeners();
}
// 클럽의 모든 이벤트 가져오기
Future<void> fetchClubEvents() async {
print('fetchClubEvents 호출됨: token=$_token');
_isLoading = true;
notifyListeners();
try {
// 클럽 ID 가져오기
final prefs = await SharedPreferences.getInstance();
final clubId = prefs.getString(ApiConfig.clubIdKey);
if (clubId == null) {
throw Exception('선택된 클럽이 없습니다');
}
final data = await _apiService.post(
'${ApiConfig.clubs}/events',
data: {'clubId': clubId},
);
// 응답 데이터가 리스트 형태로 직접 왔는지 확인
if (data is List) {
final List<dynamic> eventsData = data;
_events = eventsData
.map((eventData) => Event.fromJson(eventData))
.toList();
} else {
// 응답 데이터가 객체 형태로 왔을 경우 events 키를 통해 접근
final List<dynamic> eventsData = data['events'] ?? [];
_events = eventsData
.map((eventData) => Event.fromJson(eventData))
.toList();
}
_isLoading = false;
notifyListeners();
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('이벤트 목록을 불러오는데 실패했습니다: $e');
}
}
// ID로 이벤트 정보 가져오기
Future<Event> fetchEventById(String eventId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/detail',
data: {'eventId': eventId},
);
return Event.fromJson(data['event']);
} catch (e) {
throw Exception('이벤트 정보를 불러오는데 실패했습니다: $e');
}
}
// 이벤트 생성
Future<Event> createEvent(Map<String, dynamic> eventData) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events',
data: eventData,
);
final newEvent = Event.fromJson(data['event']);
_events.add(newEvent);
_isLoading = false;
notifyListeners();
return newEvent;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('이벤트 생성에 실패했습니다: $e');
}
}
// 이벤트 정보 업데이트
Future<Event> updateEvent(
String eventId,
Map<String, dynamic> updates,
) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.put(
'${ApiConfig.clubs}/events/$eventId',
data: updates,
);
final updatedEvent = Event.fromJson(data['event']);
// 이벤트 목록 업데이트
final index = _events.indexWhere((event) => event.id == eventId);
if (index >= 0) {
_events[index] = updatedEvent;
}
_isLoading = false;
notifyListeners();
return updatedEvent;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('이벤트 정보 업데이트에 실패했습니다: $e');
}
}
// 이벤트 삭제
Future<bool> deleteEvent(String eventId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
await _apiService.delete('${ApiConfig.clubs}/events/$eventId');
// 이벤트 목록에서 삭제
_events.removeWhere((event) => event.id == eventId);
_isLoading = false;
notifyListeners();
return true;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('이벤트 삭제에 실패했습니다: $e');
}
}
// 참가자 관리 기능
// 이벤트 참가자 목록 가져오기
Future<List<Participant>> fetchEventParticipants(String eventId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/participants',
data: {'eventId': eventId},
);
final List<dynamic> participantsData = data['participants'] ?? [];
_participants = participantsData
.map((participantData) => Participant.fromJson(participantData))
.toList();
_isLoading = false;
notifyListeners();
return _participants;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('참가자 목록을 불러오는데 실패했습니다: $e');
}
}
// 참가자 추가
Future<Participant> addParticipant(
String eventId,
Map<String, dynamic> participantData,
) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/$eventId/participants',
data: participantData,
);
final newParticipant = Participant.fromJson(data['participant']);
_participants.add(newParticipant);
_isLoading = false;
notifyListeners();
return newParticipant;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('참가자 추가에 실패했습니다: $e');
}
}
// 참가자 정보 업데이트
Future<Participant> updateParticipant(
String eventId,
String participantId,
Map<String, dynamic> updates,
) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.put(
'${ApiConfig.clubs}/events/$eventId/participants/$participantId',
data: updates,
);
final updatedParticipant = Participant.fromJson(data['participant']);
// 참가자 목록 업데이트
final index = _participants.indexWhere(
(participant) => participant.id == participantId,
);
if (index >= 0) {
_participants[index] = updatedParticipant;
}
_isLoading = false;
notifyListeners();
return updatedParticipant;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('참가자 정보 업데이트에 실패했습니다: $e');
}
}
// 참가자 삭제
Future<bool> removeParticipant(String eventId, String participantId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
await _apiService.delete(
'${ApiConfig.clubs}/events/$eventId/participants/$participantId',
);
// 참가자 목록에서 삭제
_participants.removeWhere(
(participant) => participant.id == participantId,
);
_isLoading = false;
notifyListeners();
return true;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('참가자 삭제에 실패했습니다: $e');
}
}
// 참가자 상태 업데이트
Future<Participant> updateParticipantStatus(
String eventId,
String participantId,
String status,
) async {
return updateParticipant(eventId, participantId, {'status': status});
}
// 점수 관리 기능
// 이벤트 점수 목록 가져오기
Future<List<Score>> fetchEventScores(String eventId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/scores',
data: {'eventId': eventId},
);
final List<dynamic> scoresData = data['scores'] ?? [];
_scores = scoresData
.map((scoreData) => Score.fromJson(scoreData))
.toList();
_isLoading = false;
notifyListeners();
return _scores;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('점수 목록을 불러오는데 실패했습니다: $e');
}
}
// 점수 추가
Future<Score> addScore(String eventId, Map<String, dynamic> scoreData) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/$eventId/scores',
data: scoreData,
);
final newScore = Score.fromJson(data['score']);
_scores.add(newScore);
_isLoading = false;
notifyListeners();
return newScore;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('점수 추가에 실패했습니다: $e');
}
}
// 점수 업데이트
Future<Score> updateScore(
String eventId,
String scoreId,
Map<String, dynamic> updates,
) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.put(
'${ApiConfig.clubs}/events/$eventId/scores/$scoreId',
data: updates,
);
final updatedScore = Score.fromJson(data['score']);
// 점수 목록 업데이트
final index = _scores.indexWhere((score) => score.id == scoreId);
if (index >= 0) {
_scores[index] = updatedScore;
}
_isLoading = false;
notifyListeners();
return updatedScore;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('점수 업데이트에 실패했습니다: $e');
}
}
// 점수 삭제
Future<bool> deleteScore(String eventId, String scoreId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
await _apiService.delete(
'${ApiConfig.clubs}/events/$eventId/scores/$scoreId',
);
// 점수 목록에서 삭제
_scores.removeWhere((score) => score.id == scoreId);
_isLoading = false;
notifyListeners();
return true;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('점수 삭제에 실패했습니다: $e');
}
}
// 팀 관리 기능
// 이벤트 팀 목록 가져오기
Future<List<Team>> fetchEventTeams(String eventId) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/teams',
data: {'eventId': eventId},
);
final List<dynamic> teamsData = data['teams'] ?? [];
_teams = teamsData.map((teamData) => Team.fromJson(teamData)).toList();
_isLoading = false;
notifyListeners();
return _teams;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('팀 목록을 불러오는데 실패했습니다: $e');
}
}
// 팀 생성
Future<List<Team>> generateTeams(
String eventId,
Map<String, dynamic> teamConfig,
) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final data = await _apiService.post(
'${ApiConfig.clubs}/events/$eventId/teams/generate',
data: teamConfig,
);
final List<dynamic> teamsData = data['teams'] ?? [];
_teams = teamsData.map((teamData) => Team.fromJson(teamData)).toList();
_isLoading = false;
notifyListeners();
return _teams;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('팀 생성에 실패했습니다: $e');
}
}
// 팀 저장
Future<bool> saveTeams(String eventId, List<Team> teams) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
await _apiService.post(
'${ApiConfig.clubs}/events/$eventId/teams/save',
data: {'teams': teams.map((team) => team.toJson()).toList()},
);
_teams = teams;
_isLoading = false;
notifyListeners();
return true;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('팀 저장에 실패했습니다: $e');
}
}
// 파일에서 이벤트 일괄 생성
Future<List<Event>> createEventsFromFile(
List<Map<String, dynamic>> eventsData,
) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
final List<Event> createdEvents = [];
// 각 이벤트 데이터에 클럽 ID 추가
for (var eventData in eventsData) {
eventData['clubId'] = _clubId;
// null 값 처리 - 빈 문자열을 명시적 null로 변환
eventData.forEach((key, value) {
if (value is String && value.isEmpty) {
eventData[key] = null;
}
});
// 이벤트 생성 API 호출
final data = await _apiService.post(
'${ApiConfig.clubs}/events',
data: eventData,
);
final newEvent = Event.fromJson(data['event']);
createdEvents.add(newEvent);
_events.add(newEvent);
}
_isLoading = false;
notifyListeners();
return createdEvents;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('파일에서 이벤트 생성에 실패했습니다: $e');
}
}
// 이벤트 복제
Future<Event> cloneEvent(String eventId, {String? newName}) async {
if (_token == null || _clubId == null) {
throw Exception('인증 또는 클럽 정보가 필요합니다');
}
_isLoading = true;
notifyListeners();
try {
// 원본 이벤트 정보 가져오기
final originalEvent = await fetchEventById(eventId);
// 복제할 이벤트 데이터 준비
final Map<String, dynamic> cloneData = {
'clubId': _clubId,
'title': newName ?? '${originalEvent.title} (복사본)',
'description': originalEvent.description,
'location': originalEvent.location,
'type': originalEvent.type,
'status': 'draft', // 복제된 이벤트는 초안 상태로 시작
'startDate': originalEvent.startDate.toIso8601String(),
'endDate': originalEvent.endDate?.toIso8601String(),
'maxParticipants': originalEvent.maxParticipants,
'participantFee': originalEvent.participantFee,
'gameCount': originalEvent.gameCount,
'publicHash': originalEvent.publicHash,
'accessPassword': originalEvent.accessPassword,
'isActive': true,
};
// 이벤트 생성 API 호출
final data = await _apiService.post(
'${ApiConfig.clubs}/events',
data: cloneData,
);
final newEvent = Event.fromJson(data['event']);
_events.add(newEvent);
_isLoading = false;
notifyListeners();
return newEvent;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception('이벤트 복제에 실패했습니다: $e');
}
}
}