LCOV - code coverage report

Current view: | top level - lib/screens/score - member_statistics_screen.dart |  |  | Coverage | Total | Hit
Test: | lcov.info |  | Lines: | 0.0 % | 256 | 0
Test Date: | 2025-08-12 03:21:51 |  | Functions: | - | 0 | 0

                Line data    Source code

           1              : import 'package:flutter/material.dart';
           2              : import 'package:provider/provider.dart';
           3              : import 'package:intl/intl.dart';
           4              : import 'package:fl_chart/fl_chart.dart';
           5              :
           6              : import '../../services/auth_service.dart';
           7              : import '../../services/club_service.dart';
           8              : import '../../services/member_service.dart';
           9              : import '../../services/score_service.dart';
          10              : import '../../models/member_model.dart';
          11              : import '../../models/score_model.dart';
          12              : import 'score_entry_screen.dart';
          13              :
          14              : class MemberStatisticsScreen extends StatefulWidget {
          15              :   final String memberId;
          16              :
          17            0 :   const MemberStatisticsScreen({super.key, required this.memberId});
          18              :
          19            0 :   @override
          20            0 :   State<MemberStatisticsScreen> createState() => _MemberStatisticsScreenState();
          21              : }
          22              :
          23              : class _MemberStatisticsScreenState extends State<MemberStatisticsScreen>
          24              :     with SingleTickerProviderStateMixin {
          25              :   bool _isLoading = false;
          26              :   bool _isInit = false;
          27              :   late TabController _tabController;
          28              :
          29              :   Member? _member;
          30              :   List<Score> _scores = [];
          31              :   ScoreStatistics? _statistics;
          32              :
          33            0 :   @override
          34              :   void initState() {
          35            0 :     super.initState();
          36            0 :     _tabController = TabController(length: 2, vsync: this);
          37              :   }
          38              :
          39            0 :   @override
          40              :   void dispose() {
          41            0 :     _tabController.dispose();
          42            0 :     super.dispose();
          43              :   }
          44              :
          45            0 :   @override
          46              :   void didChangeDependencies() {
          47            0 :     super.didChangeDependencies();
          48            0 :     if (!_isInit) {
          49            0 :       _loadMemberData();
          50            0 :       _isInit = true;
          51              :     }
          52              :   }
          53              :
          54            0 :   Future<void> _loadMemberData() async {
          55            0 :     setState(() {
          56            0 :       _isLoading = true;
          57              :     });
          58              :
          59              :     try {
          60            0 :       final authService = Provider.of<AuthService>(context, listen: false);
          61            0 :       final clubService = Provider.of<ClubService>(context, listen: false);
          62            0 :       final memberService = Provider.of<MemberService>(context, listen: false);
          63            0 :       final scoreService = Provider.of<ScoreService>(context, listen: false);
          64              :
          65            0 :       if (clubService.currentClub != null) {
          66              :         // 회원 정보 로드
          67            0 :         _member = await memberService.fetchMemberById(widget.memberId);
          68              :
          69              :         // 점수 서비스 초기화
          70            0 :         scoreService.initialize(authService.token!);
          71              :
          72              :         // 회원 점수 및 통계 로드
          73            0 :         await Future.wait([
          74            0 :           scoreService.fetchMemberScores(widget.memberId).then((scores) {
          75            0 :             _scores = scores;
          76              :           }),
          77            0 :           scoreService.fetchMemberStatistics(widget.memberId).then((stats) {
          78            0 :             _statistics = stats;
          79              :           }),
          80              :         ]);
          81              :       }
          82              :     } catch (e) {
          83            0 :       ScaffoldMessenger.of(
          84            0 :         context,
          85            0 :       ).showSnackBar(SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $e')));
          86              :     } finally {
          87            0 :       setState(() {
          88            0 :         _isLoading = false;
          89              :       });
          90              :     }
          91              :   }
          92              :
          93            0 :   @override
          94              :   Widget build(BuildContext context) {
          95            0 :     return Scaffold(
          96            0 :       appBar: AppBar(
          97            0 :         title: Text(_member?.name ?? '회원 통계'),
          98            0 :         bottom: TabBar(
          99            0 :           controller: _tabController,
         100              :           tabs: const [
         101              :             Tab(text: '통계'),
         102              :             Tab(text: '점수 기록'),
         103              :           ],
         104              :         ),
         105              :       ),
         106            0 :       body: _isLoading
         107              :           ? const Center(child: CircularProgressIndicator())
         108            0 :           : TabBarView(
         109            0 :               controller: _tabController,
         110            0 :               children: [_buildStatisticsTab(), _buildScoresTab()],
         111              :             ),
         112            0 :       floatingActionButton: FloatingActionButton(
         113            0 :         onPressed: () async {
         114            0 :           await Navigator.of(context).push(
         115            0 :             MaterialPageRoute(
         116            0 :               builder: (context) => ScoreEntryScreen(memberId: widget.memberId),
         117              :             ),
         118              :           );
         119              :           // 화면으로 돌아왔을 때 데이터 새로고침
         120            0 :           _loadMemberData();
         121              :         },
         122              :         backgroundColor: Colors.blue,
         123              :         child: const Icon(Icons.add, color: Colors.white),
         124              :       ),
         125              :     );
         126              :   }
         127              :
         128            0 :   Widget _buildStatisticsTab() {
         129            0 :     if (_statistics == null) {
         130              :       return const Center(child: Text('통계 데이터가 없습니다'));
         131              :     }
         132              :
         133            0 :     return RefreshIndicator(
         134            0 :       onRefresh: _loadMemberData,
         135            0 :       child: SingleChildScrollView(
         136              :         physics: const AlwaysScrollableScrollPhysics(),
         137              :         padding: const EdgeInsets.all(16.0),
         138            0 :         child: Column(
         139              :           crossAxisAlignment: CrossAxisAlignment.start,
         140            0 :           children: [
         141              :             // 회원 정보 카드
         142            0 :             if (_member != null) _buildMemberInfoCard(),
         143            0 :             const SizedBox(height: 24),
         144              :
         145              :             // 주요 통계 카드
         146            0 :             _buildMainStatsCard(),
         147            0 :             const SizedBox(height: 24),
         148              :
         149              :             // 추가 통계 정보
         150            0 :             if (_statistics!.additionalStats != null)
         151            0 :               _buildAdditionalStatsCard(),
         152              :
         153              :             // 통계 그래프
         154            0 :             const SizedBox(height: 24),
         155            0 :             Card(
         156            0 :               child: Padding(
         157              :                 padding: const EdgeInsets.all(16.0),
         158            0 :                 child: Column(
         159              :                   crossAxisAlignment: CrossAxisAlignment.start,
         160            0 :                   children: [
         161              :                     const Text(
         162              :                       '점수 추이',
         163              :                       style: TextStyle(
         164              :                         fontSize: 16,
         165              :                         fontWeight: FontWeight.bold,
         166              :                       ),
         167              :                     ),
         168              :                     const SizedBox(height: 16),
         169            0 :                     SizedBox(height: 200, child: _buildScoreChart()),
         170              :                   ],
         171              :                 ),
         172              :               ),
         173              :             ),
         174              :           ],
         175              :         ),
         176              :       ),
         177              :     );
         178              :   }
         179              :
         180            0 :   Widget _buildMemberInfoCard() {
         181            0 :     return Card(
         182              :       elevation: 2,
         183            0 :       shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
         184            0 :       child: Padding(
         185              :         padding: const EdgeInsets.all(16.0),
         186            0 :         child: Row(
         187            0 :           children: [
         188            0 :             CircleAvatar(
         189              :               radius: 30,
         190            0 :               backgroundColor: Colors.blue.shade100,
         191            0 :               backgroundImage: _member!.profileImage != null
         192            0 :                   ? NetworkImage(_member!.profileImage!)
         193              :                   : null,
         194            0 :               child: _member!.profileImage == null
         195            0 :                   ? Text(
         196            0 :                       _member!.name.isNotEmpty
         197            0 :                           ? _member!.name[0].toUpperCase()
         198              :                           : '?',
         199              :                       style: const TextStyle(
         200              :                         fontSize: 24,
         201              :                         color: Colors.blue,
         202              :                         fontWeight: FontWeight.bold,
         203              :                       ),
         204              :                     )
         205              :                   : null,
         206              :             ),
         207              :             const SizedBox(width: 16),
         208            0 :             Expanded(
         209            0 :               child: Column(
         210              :                 crossAxisAlignment: CrossAxisAlignment.start,
         211            0 :                 children: [
         212            0 :                   Text(
         213            0 :                     _member!.name,
         214              :                     style: const TextStyle(
         215              :                       fontSize: 20,
         216              :                       fontWeight: FontWeight.bold,
         217              :                     ),
         218              :                   ),
         219              :                   const SizedBox(height: 4),
         220            0 :                   Text(
         221            0 :                     _member!.email,
         222            0 :                     style: TextStyle(color: Colors.grey[600]),
         223              :                   ),
         224            0 :                   if (_member!.phone != null)
         225            0 :                     Text(
         226            0 :                       _member!.phone!,
         227            0 :                       style: TextStyle(color: Colors.grey[600]),
         228              :                     ),
         229              :                 ],
         230              :               ),
         231              :             ),
         232              :           ],
         233              :         ),
         234              :       ),
         235              :     );
         236              :   }
         237              :
         238            0 :   Widget _buildMainStatsCard() {
         239            0 :     return Card(
         240              :       elevation: 2,
         241            0 :       shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
         242            0 :       child: Padding(
         243              :         padding: const EdgeInsets.all(16.0),
         244            0 :         child: Column(
         245              :           crossAxisAlignment: CrossAxisAlignment.start,
         246            0 :           children: [
         247              :             const Text(
         248              :               '주요 통계',
         249              :               style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
         250              :             ),
         251              :             const SizedBox(height: 16),
         252            0 :             Row(
         253            0 :               children: [
         254            0 :                 Expanded(
         255            0 :                   child: _buildStatItem(
         256              :                     label: '평균 점수',
         257            0 :                     value: _statistics!.average.toStringAsFixed(1),
         258              :                     icon: Icons.score,
         259              :                     color: Colors.blue,
         260              :                   ),
         261              :                 ),
         262            0 :                 Expanded(
         263            0 :                   child: _buildStatItem(
         264              :                     label: '최고 점수',
         265            0 :                     value: _statistics!.highScore.toString(),
         266              :                     icon: Icons.emoji_events,
         267              :                     color: Colors.amber,
         268              :                   ),
         269              :                 ),
         270              :               ],
         271              :             ),
         272              :             const SizedBox(height: 16),
         273            0 :             Row(
         274            0 :               children: [
         275            0 :                 Expanded(
         276            0 :                   child: _buildStatItem(
         277              :                     label: '최저 점수',
         278            0 :                     value: _statistics!.lowScore.toString(),
         279              :                     icon: Icons.arrow_downward,
         280              :                     color: Colors.red,
         281              :                   ),
         282              :                 ),
         283            0 :                 Expanded(
         284            0 :                   child: _buildStatItem(
         285              :                     label: '게임 수',
         286            0 :                     value: _statistics!.gamesPlayed.toString(),
         287              :                     icon: Icons.sports,
         288              :                     color: Colors.green,
         289              :                   ),
         290              :                 ),
         291              :               ],
         292              :             ),
         293              :           ],
         294              :         ),
         295              :       ),
         296              :     );
         297              :   }
         298              :
         299            0 :   Widget _buildStatItem({
         300              :     required String label,
         301              :     required String value,
         302              :     required IconData icon,
         303              :     required Color color,
         304              :   }) {
         305            0 :     return Column(
         306            0 :       children: [
         307            0 :         Icon(icon, size: 32, color: color),
         308              :         const SizedBox(height: 8),
         309            0 :         Text(
         310              :           value,
         311            0 :           style: TextStyle(
         312              :             fontSize: 20,
         313              :             fontWeight: FontWeight.bold,
         314              :             color: color,
         315              :           ),
         316              :         ),
         317            0 :         Text(label, style: TextStyle(fontSize: 14, color: Colors.grey[600])),
         318              :       ],
         319              :     );
         320              :   }
         321              :
         322            0 :   Widget _buildAdditionalStatsCard() {
         323            0 :     final additionalStats = _statistics!.additionalStats!;
         324              :
         325            0 :     return Card(
         326              :       elevation: 2,
         327            0 :       shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
         328            0 :       child: Padding(
         329              :         padding: const EdgeInsets.all(16.0),
         330            0 :         child: Column(
         331              :           crossAxisAlignment: CrossAxisAlignment.start,
         332            0 :           children: [
         333              :             const Text(
         334              :               '추가 통계',
         335              :               style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
         336              :             ),
         337              :             const SizedBox(height: 16),
         338            0 :             ...additionalStats.entries.map((entry) {
         339            0 :               return Padding(
         340              :                 padding: const EdgeInsets.only(bottom: 8.0),
         341            0 :                 child: Row(
         342              :                   mainAxisAlignment: MainAxisAlignment.spaceBetween,
         343            0 :                   children: [
         344            0 :                     Text(entry.key, style: const TextStyle(fontSize: 16)),
         345            0 :                     Text(
         346            0 :                       entry.value.toString(),
         347              :                       style: const TextStyle(
         348              :                         fontSize: 16,
         349              :                         fontWeight: FontWeight.bold,
         350              :                       ),
         351              :                     ),
         352              :                   ],
         353              :                 ),
         354              :               );
         355              :             }),
         356              :           ],
         357              :         ),
         358              :       ),
         359              :     );
         360              :   }
         361              :
         362            0 :   Widget _buildScoresTab() {
         363            0 :     if (_scores.isEmpty) {
         364              :       return const Center(child: Text('기록된 점수가 없습니다'));
         365              :     }
         366              :
         367              :     // 날짜 기준으로 정렬 (최신순)
         368            0 :     final sortedScores = [..._scores];
         369            0 :     sortedScores.sort((a, b) => b.date.compareTo(a.date));
         370              :
         371            0 :     return RefreshIndicator(
         372            0 :       onRefresh: _loadMemberData,
         373            0 :       child: ListView.builder(
         374              :         padding: const EdgeInsets.all(8.0),
         375            0 :         itemCount: sortedScores.length,
         376            0 :         itemBuilder: (context, index) {
         377            0 :           final score = sortedScores[index];
         378            0 :           return _buildScoreCard(score);
         379              :         },
         380              :       ),
         381              :     );
         382              :   }
         383              :
         384            0 :   Widget _buildScoreCard(Score score) {
         385            0 :     final dateFormat = DateFormat('yyyy년 MM월 dd일');
         386              :
         387            0 :     return Card(
         388              :       margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
         389            0 :       shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
         390            0 :       child: ExpansionTile(
         391            0 :         title: Row(
         392            0 :           children: [
         393            0 :             Text(
         394            0 :               score.totalScore.toString(),
         395              :               style: const TextStyle(
         396              :                 fontSize: 20,
         397              :                 fontWeight: FontWeight.bold,
         398              :                 color: Colors.blue,
         399              :               ),
         400              :             ),
         401              :             const SizedBox(width: 16),
         402            0 :             Expanded(
         403            0 :               child: Column(
         404              :                 crossAxisAlignment: CrossAxisAlignment.start,
         405            0 :                 children: [
         406            0 :                   Text(
         407            0 :                     dateFormat.format(score.date),
         408              :                     style: const TextStyle(fontSize: 14),
         409              :                   ),
         410            0 :                   if (score.notes != null && score.notes!.isNotEmpty)
         411            0 :                     Text(
         412            0 :                       score.notes!,
         413            0 :                       style: TextStyle(fontSize: 12, color: Colors.grey[600]),
         414              :                       maxLines: 1,
         415              :                       overflow: TextOverflow.ellipsis,
         416              :                     ),
         417              :                 ],
         418              :               ),
         419              :             ),
         420              :           ],
         421              :         ),
         422            0 :         children: [
         423            0 :           Padding(
         424              :             padding: const EdgeInsets.all(16.0),
         425            0 :             child: Column(
         426              :               crossAxisAlignment: CrossAxisAlignment.start,
         427            0 :               children: [
         428              :                 const Text(
         429              :                   '프레임 점수',
         430              :                   style: TextStyle(fontWeight: FontWeight.bold),
         431              :                 ),
         432              :                 const SizedBox(height: 8),
         433            0 :                 _buildFrameScores(score.frames),
         434            0 :                 if (score.notes != null && score.notes!.isNotEmpty) ...[
         435              :                   const SizedBox(height: 16),
         436              :                   const Text(
         437              :                     '메모',
         438              :                     style: TextStyle(fontWeight: FontWeight.bold),
         439              :                   ),
         440              :                   const SizedBox(height: 4),
         441            0 :                   Text(score.notes!),
         442              :                 ],
         443            0 :                 const SizedBox(height: 16),
         444            0 :                 Row(
         445              :                   mainAxisAlignment: MainAxisAlignment.end,
         446            0 :                   children: [
         447            0 :                     TextButton.icon(
         448              :                       icon: const Icon(Icons.edit, size: 16),
         449              :                       label: const Text('수정'),
         450            0 :                       onPressed: () {
         451              :                         // 점수 수정 기능 (추후 구현)
         452            0 :                         ScaffoldMessenger.of(context).showSnackBar(
         453              :                           const SnackBar(content: Text('점수 수정 기능은 아직 개발 중입니다')),
         454              :                         );
         455              :                       },
         456              :                     ),
         457              :                     const SizedBox(width: 8),
         458            0 :                     TextButton.icon(
         459              :                       icon: const Icon(
         460              :                         Icons.delete,
         461              :                         size: 16,
         462              :                         color: Colors.red,
         463              :                       ),
         464              :                       label: const Text(
         465              :                         '삭제',
         466              :                         style: TextStyle(color: Colors.red),
         467              :                       ),
         468            0 :                       onPressed: () {
         469            0 :                         _showDeleteConfirmationDialog(score);
         470              :                       },
         471              :                     ),
         472              :                   ],
         473              :                 ),
         474              :               ],
         475              :             ),
         476              :           ),
         477              :         ],
         478              :       ),
         479              :     );
         480              :   }
         481              :
         482            0 :   Widget _buildFrameScores(List<int> frames) {
         483            0 :     return Container(
         484              :       padding: const EdgeInsets.all(8),
         485            0 :       decoration: BoxDecoration(
         486            0 :         color: Colors.grey[100],
         487            0 :         borderRadius: BorderRadius.circular(8),
         488              :       ),
         489            0 :       child: Row(
         490            0 :         children: List.generate(10, (index) {
         491            0 :           return Expanded(
         492            0 :             child: Container(
         493              :               padding: const EdgeInsets.symmetric(vertical: 8),
         494            0 :               decoration: BoxDecoration(
         495            0 :                 border: Border.all(color: Colors.grey[300]!),
         496              :               ),
         497            0 :               child: Column(
         498            0 :                 children: [
         499            0 :                   Text(
         500            0 :                     '${index + 1}',
         501            0 :                     style: TextStyle(fontSize: 10, color: Colors.grey[600]),
         502              :                   ),
         503              :                   const SizedBox(height: 4),
         504            0 :                   Text(
         505            0 :                     index < frames.length ? frames[index].toString() : '-',
         506              :                     style: const TextStyle(fontWeight: FontWeight.bold),
         507              :                     textAlign: TextAlign.center,
         508              :                   ),
         509              :                 ],
         510              :               ),
         511              :             ),
         512              :           );
         513              :         }),
         514              :       ),
         515              :     );
         516              :   }
         517              :
         518            0 :   Widget _buildScoreChart() {
         519            0 :     if (_scores.isEmpty) {
         520              :       return const Center(child: Text('점수 데이터가 없습니다'));
         521              :     }
         522              :
         523              :     // 날짜 기준으로 정렬 (오래된 순)
         524            0 :     final sortedScores = [..._scores];
         525            0 :     sortedScores.sort((a, b) => a.date.compareTo(b.date));
         526              :
         527              :     // 최대 10개의 최근 점수만 표시
         528            0 :     final displayScores = sortedScores.length > 10
         529            0 :         ? sortedScores.sublist(sortedScores.length - 10)
         530              :         : sortedScores;
         531              :
         532              :     // 최소/최대 점수 계산 (Y축 범위 설정용)
         533              :     final minScore =
         534            0 :         displayScores.map((s) => s.totalScore).reduce((a, b) => a < b ? a : b) -
         535              :         10;
         536              :     final maxScore =
         537            0 :         displayScores.map((s) => s.totalScore).reduce((a, b) => a > b ? a : b) +
         538              :         10;
         539              :
         540              :     // 그래프 데이터 포인트 생성
         541            0 :     final spots = <FlSpot>[];
         542            0 :     for (int i = 0; i < displayScores.length; i++) {
         543            0 :       spots.add(FlSpot(i.toDouble(), displayScores[i].totalScore.toDouble()));
         544              :     }
         545              :
         546            0 :     return LineChart(
         547            0 :       LineChartData(
         548            0 :         gridData: FlGridData(
         549              :           show: true,
         550              :           drawVerticalLine: true,
         551              :           horizontalInterval: 20,
         552              :           verticalInterval: 1,
         553              :         ),
         554            0 :         titlesData: FlTitlesData(
         555              :           show: true,
         556              :           rightTitles: const AxisTitles(
         557              :             sideTitles: SideTitles(showTitles: false),
         558              :           ),
         559              :           topTitles: const AxisTitles(
         560              :             sideTitles: SideTitles(showTitles: false),
         561              :           ),
         562            0 :           bottomTitles: AxisTitles(
         563            0 :             sideTitles: SideTitles(
         564              :               showTitles: true,
         565              :               reservedSize: 30,
         566              :               interval: 1,
         567            0 :               getTitlesWidget: (value, meta) {
         568            0 :                 final index = value.toInt();
         569            0 :                 if (index >= 0 && index < displayScores.length) {
         570            0 :                   return Text(
         571            0 :                     DateFormat('MM/dd').format(displayScores[index].date),
         572              :                     style: const TextStyle(fontSize: 10),
         573              :                   );
         574              :                 }
         575              :                 return const SizedBox();
         576              :               },
         577              :             ),
         578              :           ),
         579            0 :           leftTitles: AxisTitles(
         580            0 :             sideTitles: SideTitles(
         581              :               showTitles: true,
         582              :               interval: 50,
         583            0 :               getTitlesWidget: (value, meta) {
         584            0 :                 return Text(
         585            0 :                   value.toInt().toString(),
         586              :                   style: const TextStyle(fontSize: 10),
         587              :                 );
         588              :               },
         589              :               reservedSize: 40,
         590              :             ),
         591              :           ),
         592              :         ),
         593            0 :         borderData: FlBorderData(
         594              :           show: true,
         595            0 :           border: Border.all(color: Colors.grey.shade300),
         596              :         ),
         597              :         minX: 0,
         598            0 :         maxX: displayScores.length - 1.0,
         599            0 :         minY: minScore.toDouble(),
         600            0 :         maxY: maxScore.toDouble(),
         601            0 :         lineBarsData: [
         602            0 :           LineChartBarData(
         603              :             spots: spots,
         604              :             isCurved: false,
         605              :             color: Colors.blue,
         606              :             barWidth: 3,
         607              :             isStrokeCapRound: true,
         608              :             dotData: const FlDotData(show: true),
         609            0 :             belowBarData: BarAreaData(
         610              :               show: true,
         611            0 :               color: Colors.blue.withOpacity(0.2),
         612              :             ),
         613              :           ),
         614              :         ],
         615              :       ),
         616              :     );
         617              :   }
         618              :
         619            0 :   void _showDeleteConfirmationDialog(Score score) {
         620            0 :     showDialog(
         621            0 :       context: context,
         622            0 :       builder: (context) => AlertDialog(
         623              :         title: const Text('점수 삭제'),
         624              :         content: const Text('이 점수 기록을 정말 삭제하시겠습니까?'),
         625            0 :         actions: [
         626            0 :           TextButton(
         627            0 :             onPressed: () => Navigator.of(context).pop(),
         628              :             child: const Text('취소'),
         629              :           ),
         630            0 :           TextButton(
         631            0 :             onPressed: () async {
         632            0 :               Navigator.of(context).pop();
         633              :
         634              :               try {
         635            0 :                 final scoreService = Provider.of<ScoreService>(
         636              :                   context,
         637              :                   listen: false,
         638              :                 );
         639            0 :                 await scoreService.deleteScore(score.id);
         640              :
         641              :                 // 데이터 새로고침
         642            0 :                 _loadMemberData();
         643              :
         644            0 :                 if (mounted) {
         645            0 :                   ScaffoldMessenger.of(
         646              :                     context,
         647            0 :                   ).showSnackBar(const SnackBar(content: Text('점수가 삭제되었습니다')));
         648              :                 }
         649              :               } catch (e) {
         650            0 :                 ScaffoldMessenger.of(
         651              :                   context,
         652            0 :                 ).showSnackBar(SnackBar(content: Text('점수 삭제에 실패했습니다: $e')));
         653              :               }
         654              :             },
         655            0 :             style: TextButton.styleFrom(foregroundColor: Colors.red),
         656              :             child: const Text('삭제'),
         657              :           ),
         658              :         ],
         659              :       ),
         660              :     );
         661              :   }
         662              : }

Generated by: LCOV version 2.3.1-1