LCOV - code coverage report
Current view: top level - lib/services - score_service.dart Coverage Total Hit
Test: lcov.info Lines: 78.4 % 134 105
Test Date: 2025-08-12 03:21:51 Functions: - 0 0

            Line data    Source code
       1              : import 'package:flutter/foundation.dart';
       2              : import 'package:shared_preferences/shared_preferences.dart';
       3              : 
       4              : import '../config/api_config.dart';
       5              : import '../models/score_model.dart';
       6              : import './api_service.dart';
       7              : 
       8              : class ScoreService with ChangeNotifier {
       9              :   List<Score> _scores = [];
      10              :   bool _isLoading = false;
      11              :   String? _token;
      12              :   String? _clubId;
      13              :   ApiService _apiService = ApiService();
      14              :   String? _memberId;
      15              :   String? _eventId;
      16              :   
      17              :   // 테스트용 생성자
      18            2 :   ScoreService.forTest(ApiService apiService, {String? clubId, String? memberId, String? eventId}) {
      19            2 :     _apiService = apiService;
      20              :     if (clubId != null) {
      21            2 :       _clubId = clubId;
      22              :     }
      23              :     if (memberId != null) {
      24            0 :       _memberId = memberId;
      25              :     }
      26              :     if (eventId != null) {
      27            0 :       _eventId = eventId;
      28              :     }
      29              :   }
      30              :   
      31              :   // 테스트용 getter
      32            2 :   String? get testMemberId => _memberId;
      33            2 :   String? get testEventId => _eventId;
      34              :   
      35              :   // 기본 생성자
      36            0 :   ScoreService();
      37              : 
      38            6 :   List<Score> get scores => [..._scores];
      39            0 :   bool get isLoading => _isLoading;
      40              : 
      41              :   // 초기화 함수
      42            2 :   void initialize(String token) {
      43            2 :     _token = token;
      44            4 :     _apiService.setToken(token);
      45              :   }
      46              : 
      47              :   // 회원 ID 설정
      48            1 :   void setMemberId(String memberId) {
      49            1 :     _memberId = memberId;
      50            1 :     notifyListeners();
      51              :   }
      52              : 
      53              :   // 이벤트 ID 설정
      54            1 :   void setEventId(String eventId) {
      55            1 :     _eventId = eventId;
      56            1 :     notifyListeners();
      57              :   }
      58              : 
      59              :   // 클럽의 모든 점수 가져오기
      60            2 :   Future<void> fetchClubScores() async {
      61            6 :     print('fetchClubScores 호출됨: token=$_token');
      62              : 
      63            2 :     _isLoading = true;
      64            2 :     notifyListeners();
      65              : 
      66              :     try {
      67              :       // 클럽 ID 가져오기
      68            2 :       final prefs = await SharedPreferences.getInstance();
      69            2 :       final clubId = prefs.getString(ApiConfig.clubIdKey);
      70              : 
      71              :       if (clubId == null) {
      72            0 :         throw Exception('선택된 클럽이 없습니다');
      73              :       }
      74              : 
      75            4 :       final data = await _apiService.post(
      76              :         '${ApiConfig.clubs}/scores',
      77            2 :         data: {'clubId': clubId},
      78              :       );
      79              : 
      80              :       // 응답 데이터가 리스트 형태로 직접 왔는지 확인
      81            2 :       if (data is List) {
      82              :         final List<dynamic> scoresData = data;
      83            2 :         _scores = scoresData
      84            6 :             .map((scoreData) => Score.fromJson(scoreData))
      85            2 :             .toList();
      86              :       } else {
      87              :         // 응답 데이터가 객체 형태로 왔을 경우 scores 키를 통해 접근
      88            1 :         final List<dynamic> scoresData = data['scores'] ?? [];
      89            1 :         _scores = scoresData
      90            3 :             .map((scoreData) => Score.fromJson(scoreData))
      91            1 :             .toList();
      92              :       }
      93              : 
      94            2 :       _isLoading = false;
      95            2 :       notifyListeners();
      96              :     } catch (e) {
      97            1 :       _isLoading = false;
      98            1 :       notifyListeners();
      99            2 :       throw Exception('점수 목록을 불러오는데 실패했습니다: $e');
     100              :     }
     101              :   }
     102              : 
     103              :   // 회원의 점수 가져오기
     104            2 :   Future<List<Score>> fetchMemberScores(String memberId) async {
     105            4 :     if (_token == null || _clubId == null) {
     106            1 :       throw Exception('인증 또는 클럽 정보가 필요합니다');
     107              :     }
     108              : 
     109            2 :     _isLoading = true;
     110            2 :     notifyListeners();
     111              : 
     112              :     try {
     113            4 :       final data = await _apiService.post(
     114              :         '${ApiConfig.clubs}/members/scores',
     115            2 :         data: {'memberId': memberId},
     116              :       );
     117              : 
     118            2 :       final List<dynamic> scoresData = data['scores'];
     119              : 
     120              :       final memberScores = scoresData
     121            6 :           .map((scoreData) => Score.fromJson(scoreData))
     122            2 :           .toList();
     123              : 
     124            2 :       _isLoading = false;
     125            2 :       notifyListeners();
     126              : 
     127              :       return memberScores;
     128              :     } catch (e) {
     129            0 :       _isLoading = false;
     130            0 :       notifyListeners();
     131            0 :       throw Exception('회원 점수를 불러오는데 실패했습니다: $e');
     132              :     }
     133              :   }
     134              : 
     135              :   // 이벤트의 점수 가져오기
     136            2 :   Future<List<Score>> fetchEventScores(String eventId) async {
     137            4 :     if (_token == null || _clubId == null) {
     138            0 :       throw Exception('인증 또는 클럽 정보가 필요합니다');
     139              :     }
     140              : 
     141            2 :     _isLoading = true;
     142            2 :     notifyListeners();
     143              : 
     144              :     try {
     145            4 :       final data = await _apiService.post(
     146              :         '${ApiConfig.clubs}/events/scores',
     147            2 :         data: {'eventId': eventId},
     148              :       );
     149              : 
     150            2 :       final List<dynamic> scoresData = data['scores'];
     151              : 
     152              :       final eventScores = scoresData
     153            6 :           .map((scoreData) => Score.fromJson(scoreData))
     154            2 :           .toList();
     155              : 
     156            2 :       _isLoading = false;
     157            2 :       notifyListeners();
     158              : 
     159              :       return eventScores;
     160              :     } catch (e) {
     161            0 :       _isLoading = false;
     162            0 :       notifyListeners();
     163            0 :       throw Exception('이벤트 점수를 불러오는데 실패했습니다: $e');
     164              :     }
     165              :   }
     166              : 
     167              :   // 점수 추가
     168            2 :   Future<Score> addScore(Map<String, dynamic> scoreData) async {
     169            4 :     if (_token == null || _clubId == null) {
     170            0 :       throw Exception('인증 또는 클럽 정보가 필요합니다');
     171              :     }
     172              : 
     173            2 :     _isLoading = true;
     174            2 :     notifyListeners();
     175              : 
     176              :     try {
     177            4 :       final data = await _apiService.post(ApiConfig.scores, data: scoreData);
     178              : 
     179            4 :       final newScore = Score.fromJson(data['score']);
     180              : 
     181            4 :       _scores.add(newScore);
     182              : 
     183            2 :       _isLoading = false;
     184            2 :       notifyListeners();
     185              : 
     186              :       return newScore;
     187              :     } catch (e) {
     188            0 :       _isLoading = false;
     189            0 :       notifyListeners();
     190            0 :       throw Exception('점수 추가에 실패했습니다: $e');
     191              :     }
     192              :   }
     193              : 
     194              :   // 점수 수정
     195            2 :   Future<Score> updateScore(
     196              :     String scoreId,
     197              :     Map<String, dynamic> updates,
     198              :   ) async {
     199            4 :     if (_token == null || _clubId == null) {
     200            0 :       throw Exception('인증 또는 클럽 정보가 필요합니다');
     201              :     }
     202              : 
     203            2 :     _isLoading = true;
     204            2 :     notifyListeners();
     205              : 
     206              :     try {
     207            4 :       final data = await _apiService.put(
     208            2 :         '${ApiConfig.scores}/$scoreId',
     209              :         data: updates,
     210              :       );
     211              : 
     212            4 :       final updatedScore = Score.fromJson(data['score']);
     213              : 
     214              :       // 점수 목록 업데이트
     215           10 :       final index = _scores.indexWhere((score) => score.id == scoreId);
     216            2 :       if (index >= 0) {
     217            4 :         _scores[index] = updatedScore;
     218              :       }
     219              : 
     220            2 :       _isLoading = false;
     221            2 :       notifyListeners();
     222              : 
     223              :       return updatedScore;
     224              :     } catch (e) {
     225            0 :       _isLoading = false;
     226            0 :       notifyListeners();
     227            0 :       throw Exception('점수 수정에 실패했습니다: $e');
     228              :     }
     229              :   }
     230              : 
     231              :   // 점수 삭제
     232            2 :   Future<bool> deleteScore(String scoreId) async {
     233            4 :     if (_token == null || _clubId == null) {
     234            0 :       throw Exception('인증 또는 클럽 정보가 필요합니다');
     235              :     }
     236              : 
     237            2 :     _isLoading = true;
     238            2 :     notifyListeners();
     239              : 
     240              :     try {
     241            6 :       await _apiService.delete('${ApiConfig.scores}/$scoreId');
     242              : 
     243              :       // 점수 목록에서 삭제
     244           10 :       _scores.removeWhere((score) => score.id == scoreId);
     245              : 
     246            2 :       _isLoading = false;
     247            2 :       notifyListeners();
     248              : 
     249              :       return true;
     250              :     } catch (e) {
     251            0 :       _isLoading = false;
     252            0 :       notifyListeners();
     253            0 :       throw Exception('점수 삭제에 실패했습니다: $e');
     254              :     }
     255              :   }
     256              : 
     257              :   // 회원 통계 가져오기
     258            2 :   Future<ScoreStatistics> fetchMemberStatistics(String memberId) async {
     259            4 :     if (_token == null || _clubId == null) {
     260            0 :       throw Exception('인증 또는 클럽 정보가 필요합니다');
     261              :     }
     262              : 
     263              :     try {
     264            4 :       final data = await _apiService.post(
     265              :         '${ApiConfig.clubs}/members/stats',
     266            2 :         data: {'memberId': memberId},
     267              :       );
     268              : 
     269            4 :       return ScoreStatistics.fromJson(data['statistics']);
     270              :     } catch (e) {
     271            2 :       throw Exception('회원 통계를 불러오는데 실패했습니다: $e');
     272              :     }
     273              :   }
     274              : 
     275              :   // 클럽 통계 가져오기
     276            2 :   Future<Map<String, ScoreStatistics>> fetchClubStatistics() async {
     277            2 :     if (_token == null) {
     278            0 :       throw Exception('인증 정보가 필요합니다');
     279              :     }
     280              : 
     281              :     try {
     282              :       // 클럽 ID 가져오기
     283            2 :       final prefs = await SharedPreferences.getInstance();
     284            2 :       final clubId = prefs.getString(ApiConfig.clubIdKey);
     285              : 
     286              :       if (clubId == null) {
     287            0 :         throw Exception('선택된 클럽이 없습니다');
     288              :       }
     289              : 
     290            4 :       final data = await _apiService.post(
     291              :         '${ApiConfig.clubs}/scores/stats',
     292            2 :         data: {'clubId': clubId},
     293              :       );
     294              : 
     295            2 :       final Map<String, ScoreStatistics> statistics = {};
     296              : 
     297            2 :       if (data['statistics'] != null) {
     298              :         final Map<String, dynamic> statsData =
     299            2 :             data['statistics'] as Map<String, dynamic>;
     300              : 
     301            4 :         statsData.forEach((key, value) {
     302              :           if (value != null) {
     303              :             try {
     304            4 :               statistics[key] = ScoreStatistics.fromJson(value);
     305              :             } catch (e) {
     306            0 :               print('통계 변환 오류: $key - $e');
     307              :             }
     308              :           }
     309              :         });
     310              :       }
     311              : 
     312              :       return statistics;
     313              :     } catch (e) {
     314            0 :       throw Exception('클럽 통계를 불러오는데 실패했습니다: $e');
     315              :     }
     316              :   }
     317              : }
        

Generated by: LCOV version 2.3.1-1