LCOV - code coverage report
Current view: top level - lib/screens/club - event_details_screen.dart Coverage Total Hit
Test: lcov.info Lines: 0.0 % 769 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:flutter/services.dart';
       3              : import 'package:provider/provider.dart';
       4              : import 'package:intl/intl.dart';
       5              : import 'package:share_plus/share_plus.dart';
       6              : 
       7              : import '../../models/club_model.dart';
       8              : import '../../models/event_model.dart';
       9              : import '../../models/member_model.dart';
      10              : import '../../models/participant_model.dart';
      11              : import '../../models/score_model.dart';
      12              : import '../../models/team_model.dart';
      13              : import '../../models/tie_breaker_option.dart';
      14              : import '../../services/club_service.dart';
      15              : import '../../services/event_service.dart';
      16              : import '../../services/member_service.dart';
      17              : import '../../services/notification_service.dart';
      18              : import '../../utils/tie_breaker_util.dart';
      19              : import '../../widgets/loading_indicator.dart';
      20              : 
      21              : class EventDetailsScreen extends StatefulWidget {
      22              :   final Event event;
      23              : 
      24            0 :   const EventDetailsScreen({
      25              :     Key? key,
      26              :     required this.event,
      27            0 :   }) : super(key: key);
      28              : 
      29            0 :   @override
      30            0 :   State<EventDetailsScreen> createState() => _EventDetailsScreenState();
      31              : }
      32              : 
      33              : class _EventDetailsScreenState extends State<EventDetailsScreen> with SingleTickerProviderStateMixin {
      34              :   late TabController _tabController;
      35              :   List<Participant> _participants = [];
      36              :   List<Score> _scores = [];
      37              :   List<Team> _teams = [];
      38              :   List<Member> _members = [];
      39              :   Club? _club;
      40              :   bool _isLoading = true;
      41              :   int _teamGenerationMethod = 1; // 1: 팀 인원수로 나누기, 2: 팀 개수로 나누기
      42              :   final TextEditingController _teamSizeController = TextEditingController(text: '4');
      43              :   final TextEditingController _teamCountController = TextEditingController(text: '2');
      44              :   bool _showTeamTab = false;
      45              :   bool _includeHandicap = true; // 핸디캡 포함 여부
      46              : 
      47            0 :   @override
      48              :   void initState() {
      49            0 :     super.initState();
      50              :     // 테스트를 위해 팀 탭 항상 표시
      51            0 :     _showTeamTab = true;
      52              :     // 탭 컨트롤러 길이 동적 설정
      53            0 :     _tabController = TabController(length: _showTeamTab ? 4 : 3, vsync: this);
      54            0 :     _loadEventDetails();
      55              :   }
      56              : 
      57            0 :   @override
      58              :   void dispose() {
      59            0 :     _tabController.dispose();
      60            0 :     super.dispose();
      61              :   }
      62              : 
      63            0 :   Future<void> _loadEventDetails() async {
      64            0 :     setState(() {
      65            0 :       _isLoading = true;
      66              :     });
      67              : 
      68              :     try {
      69            0 :       final eventService = Provider.of<EventService>(context, listen: false);
      70            0 :       final clubService = Provider.of<ClubService>(context, listen: false);
      71            0 :       final memberService = Provider.of<MemberService>(context, listen: false);
      72              :       
      73              :       // 참가자 목록 로드
      74            0 :       final participants = await eventService.fetchEventParticipants(widget.event.id);
      75              :       
      76              :       // 점수 목록 로드
      77            0 :       final scores = await eventService.fetchEventScores(widget.event.id);
      78              :       
      79              :       // 클럽 정보 로드
      80            0 :       final club = await clubService.fetchClub(widget.event.clubId);
      81              :       
      82              :       // 회원 정보 로드 (동점자 처리 시 생년월일 사용)
      83            0 :       final memberIds = participants.map((p) => p.memberId).toList();
      84            0 :       final members = await memberService.fetchMembersByIds(widget.event.clubId, memberIds);
      85              :       
      86              :       // 팀 목록 로드 (선택적)
      87            0 :       List<Team> teams = [];
      88              :       try {
      89            0 :         teams = await eventService.fetchEventTeams(widget.event.id);
      90              :       } catch (e) {
      91              :         // 팀 기능이 없거나 오류 발생 시 무시
      92            0 :         print('팀 로드 실패: $e');
      93              :       }
      94              : 
      95            0 :       if (mounted) {
      96            0 :         setState(() {
      97            0 :           _participants = participants;
      98            0 :           _scores = scores;
      99            0 :           _teams = teams;
     100            0 :           _club = club;
     101            0 :           _members = members;
     102            0 :           _showTeamTab = true; // 테스트를 위해 팀 탭 항상 표시
     103            0 :           _isLoading = false;
     104              :         });
     105              :       }
     106              :     } catch (e) {
     107            0 :       if (mounted) {
     108            0 :         setState(() {
     109            0 :           _isLoading = false;
     110              :         });
     111            0 :         ScaffoldMessenger.of(context).showSnackBar(
     112            0 :           SnackBar(content: Text('이벤트 정보를 불러오는데 실패했습니다: $e')),
     113              :         );
     114              :       }
     115              :     }
     116              :   }
     117              : 
     118              :   // 이벤트 공유 기능
     119            0 :   void _shareEvent() {
     120              :     // 공유할 내용 구성
     121            0 :     final String eventTitle = widget.event.title;
     122            0 :     final String eventType = widget.event.type ?? '기타';
     123            0 :     final String eventDate = DateFormat('yyyy-MM-dd HH:mm').format(widget.event.startDate);
     124            0 :     final String eventLocation = widget.event.location ?? '장소 미정';
     125              :     
     126              :     // 공개 URL 생성
     127              :     String shareUrl = '';
     128            0 :     if (widget.event.publicHash != null && widget.event.publicHash!.isNotEmpty) {
     129            0 :       shareUrl = 'https://bowling.example.com/events/${widget.event.publicHash}';
     130              :     }
     131              :     
     132              :     // 공유 메시지 구성
     133              :     final String shareText = '''
     134              : [볼링 이벤트 초대]
     135              : $eventTitle
     136              : 
     137              : 유형: $eventType
     138              : 일시: $eventDate
     139              : 장소: $eventLocation
     140              : 
     141            0 : 참가자: ${_participants.length}명
     142              : 
     143            0 : ${shareUrl.isNotEmpty ? '참가 링크: $shareUrl' : ''}
     144            0 : ${widget.event.accessPassword != null && widget.event.accessPassword!.isNotEmpty ? '비밀번호: ${widget.event.accessPassword}' : ''}
     145            0 : ''';
     146              :     
     147              :     // 공유 다이얼로그 표시
     148            0 :     Share.share(shareText, subject: '볼링 이벤트: $eventTitle');
     149              :   }
     150              : 
     151            0 :   @override
     152              :   Widget build(BuildContext context) {
     153            0 :     return Scaffold(
     154            0 :       appBar: AppBar(
     155            0 :         title: Text(widget.event.title),
     156            0 :         bottom: TabBar(
     157            0 :           controller: _tabController,
     158            0 :           tabs: [
     159              :             const Tab(text: '기본 정보'),
     160              :             const Tab(text: '참가자'),
     161              :             const Tab(text: '점수'),
     162            0 :             if (_showTeamTab) const Tab(text: '팀'),
     163              :           ],
     164              :         ),
     165              :       ),
     166            0 :       body: _isLoading
     167              :           ? const LoadingIndicator()
     168            0 :           : TabBarView(
     169            0 :               controller: _tabController,
     170            0 :               children: [
     171            0 :                 _buildBasicInfoTab(),
     172            0 :                 _buildParticipantsTab(),
     173            0 :                 _buildScoresTab(),
     174            0 :                 if (_showTeamTab) _buildTeamsTab(),
     175              :               ],
     176              :             ),
     177            0 :       floatingActionButton: _buildFloatingActionButton(),
     178              :     );
     179              :   }
     180              : 
     181            0 :   Widget _buildFloatingActionButton() {
     182            0 :     final currentTab = _tabController.index;
     183              :     
     184              :     switch (currentTab) {
     185            0 :       case 0: // 기본 정보 탭
     186            0 :         return FloatingActionButton(
     187            0 :           onPressed: _editEvent,
     188              :           child: const Icon(Icons.edit),
     189              :         );
     190            0 :       case 1: // 참가자 탭
     191            0 :         return FloatingActionButton(
     192            0 :           onPressed: _addParticipant,
     193              :           child: const Icon(Icons.person_add),
     194              :         );
     195            0 :       case 2: // 점수 탭
     196            0 :         return FloatingActionButton(
     197            0 :           onPressed: _addScore,
     198              :           child: const Icon(Icons.add_chart),
     199              :         );
     200            0 :       case 3: // 팀 탭 (표시되는 경우)
     201            0 :         if (_showTeamTab) {
     202            0 :           return FloatingActionButton(
     203            0 :             onPressed: _generateTeams,
     204              :             child: const Icon(Icons.group_add),
     205              :           );
     206              :         }
     207            0 :         return Container();
     208              :       default:
     209            0 :         return Container();
     210              :     }
     211              :   }
     212              : 
     213              :   // 기본 정보 탭
     214            0 :   Widget _buildBasicInfoTab() {
     215            0 :     return SingleChildScrollView(
     216              :       padding: const EdgeInsets.all(16),
     217            0 :       child: Column(
     218              :         crossAxisAlignment: CrossAxisAlignment.start,
     219            0 :         children: [
     220              :           // 이벤트 유형 및 상태 뱃지
     221            0 :           Row(
     222            0 :             children: [
     223            0 :               Container(
     224              :                 padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
     225            0 :                 decoration: BoxDecoration(
     226            0 :                   color: _getTypeColor(widget.event.type ?? '기타'),
     227            0 :                   borderRadius: BorderRadius.circular(16),
     228              :                 ),
     229            0 :                 child: Text(
     230            0 :                   widget.event.type ?? '기타',
     231              :                   style: const TextStyle(
     232              :                     color: Colors.white,
     233              :                     fontWeight: FontWeight.bold,
     234              :                   ),
     235              :                 ),
     236              :               ),
     237              :               const SizedBox(width: 8),
     238            0 :               Container(
     239              :                 padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
     240            0 :                 decoration: BoxDecoration(
     241            0 :                   color: _getStatusColor(widget.event.status ?? '준비중'),
     242            0 :                   borderRadius: BorderRadius.circular(16),
     243              :                 ),
     244            0 :                 child: Text(
     245            0 :                   widget.event.status ?? '준비중',
     246              :                   style: const TextStyle(
     247              :                     color: Colors.white,
     248              :                     fontWeight: FontWeight.bold,
     249              :                   ),
     250              :                 ),
     251              :               ),
     252              :               const Spacer(),
     253              :               // 공유 버튼 추가
     254            0 :               IconButton(
     255              :                 icon: const Icon(Icons.share),
     256            0 :                 onPressed: _shareEvent,
     257              :                 tooltip: '이벤트 공유',
     258              :               ),
     259              :             ],
     260              :           ),
     261              :           const SizedBox(height: 16),
     262              :           
     263              :           // 이벤트 설명
     264            0 :           if (widget.event.description != null && widget.event.description!.isNotEmpty) ...[  
     265              :             const Text(
     266              :               '설명',
     267              :               style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
     268              :             ),
     269              :             const SizedBox(height: 8),
     270            0 :             Container(
     271              :               width: double.infinity,
     272              :               padding: const EdgeInsets.all(12),
     273            0 :               decoration: BoxDecoration(
     274            0 :                 color: Colors.grey[100],
     275            0 :                 borderRadius: BorderRadius.circular(8),
     276              :               ),
     277            0 :               child: Text(widget.event.description ?? ''),
     278              :             ),
     279              :             const SizedBox(height: 16),
     280              :           ],
     281              :           
     282              :           // 이벤트 정보
     283            0 :           const Text(
     284              :             '이벤트 정보',
     285              :             style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
     286              :           ),
     287            0 :           const SizedBox(height: 8),
     288            0 :           _buildInfoRow(
     289              :             Icons.calendar_today,
     290            0 :             '시작: ${DateFormat('yyyy-MM-dd HH:mm').format(widget.event.startDate)}',
     291              :           ),
     292            0 :           if (widget.event.endDate != null)
     293            0 :             _buildInfoRow(
     294              :               Icons.calendar_today,
     295            0 :               '종료: ${DateFormat('yyyy-MM-dd HH:mm').format(widget.event.endDate!)}',
     296              :             ),
     297            0 :           if (widget.event.location != null && widget.event.location!.isNotEmpty)
     298            0 :             _buildInfoRow(Icons.location_on, '장소: ${widget.event.location}'),
     299            0 :           if (widget.event.maxParticipants != null)
     300            0 :             _buildInfoRow(
     301              :               Icons.people,
     302            0 :               '최대 참가자: ${widget.event.maxParticipants}명',
     303              :             ),
     304            0 :           if (widget.event.gameCount != null)
     305            0 :             _buildInfoRow(
     306              :               Icons.sports,
     307            0 :               '게임 수: ${widget.event.gameCount}게임',
     308              :             ),
     309            0 :           if (widget.event.participantFee != null)
     310            0 :             _buildInfoRow(
     311              :               Icons.attach_money,
     312            0 :               '참가비: ${NumberFormat.currency(locale: 'ko_KR', symbol: '₩', decimalDigits: 0).format(widget.event.participantFee)}',
     313              :             ),
     314            0 :           if (widget.event.registrationDeadline != null)
     315            0 :             _buildInfoRow(
     316              :               Icons.timer,
     317            0 :               '신청마감: ${DateFormat('yyyy-MM-dd HH:mm').format(widget.event.registrationDeadline!)}',
     318              :             ),
     319            0 :           const SizedBox(height: 16),
     320              :           
     321              :           // 공개 접근 정보
     322            0 :           const Text(
     323              :             '공개 접근',
     324              :             style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
     325              :           ),
     326            0 :           const SizedBox(height: 8),
     327            0 :           if (widget.event.publicHash != null && widget.event.publicHash!.isNotEmpty) ...[  
     328            0 :             Row(
     329            0 :               children: [
     330            0 :                 Expanded(
     331            0 :                   child: _buildInfoRow(
     332              :                     Icons.link,
     333            0 :                     'https://bowling.example.com/events/${widget.event.publicHash}',
     334              :                     isSelectable: true,
     335              :                   ),
     336              :                 ),
     337            0 :                 IconButton(
     338              :                   icon: const Icon(Icons.copy),
     339            0 :                   onPressed: () {
     340            0 :                     final publicUrl = 'https://bowling.example.com/events/${widget.event.publicHash}';
     341            0 :                     Clipboard.setData(ClipboardData(text: publicUrl));
     342            0 :                     ScaffoldMessenger.of(context).showSnackBar(
     343              :                       const SnackBar(content: Text('공개 URL이 클립보드에 복사되었습니다')),
     344              :                     );
     345              :                   },
     346              :                   tooltip: 'URL 복사',
     347              :                 ),
     348              :               ],
     349              :             ),
     350              :           ],
     351            0 :           if (widget.event.accessPassword != null && widget.event.accessPassword!.isNotEmpty)
     352            0 :             _buildInfoRow(
     353              :               Icons.lock,
     354            0 :               '접근 비밀번호: ${widget.event.accessPassword}',
     355              :             ),
     356              :           
     357              :           // 참가자 정보
     358            0 :           const SizedBox(height: 16),
     359            0 :           const Text(
     360              :             '참가자 정보',
     361              :             style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
     362              :           ),
     363            0 :           const SizedBox(height: 8),
     364            0 :           _buildInfoRow(
     365              :             Icons.people,
     366            0 :             '현재 참가자: ${_participants.length}명',
     367              :           ),
     368              :           
     369              :           // 알림 설정 버튼
     370            0 :           const SizedBox(height: 24),
     371            0 :           ElevatedButton.icon(
     372            0 :             onPressed: _setEventReminders,
     373              :             icon: const Icon(Icons.notifications_active),
     374              :             label: const Text('알림 설정'),
     375            0 :             style: ElevatedButton.styleFrom(
     376              :               foregroundColor: Colors.white,
     377              :               backgroundColor: Colors.green,
     378              :               minimumSize: const Size(double.infinity, 48),
     379              :             ),
     380              :           ),
     381              :         ],
     382              :       ),
     383              :     );
     384              :   }
     385              : 
     386              :   // 참가자 탭
     387            0 :   Widget _buildParticipantsTab() {
     388            0 :     if (_participants.isEmpty) {
     389              :       return const Center(
     390              :         child: Text('참가자가 없습니다.'),
     391              :       );
     392              :     }
     393              :     
     394            0 :     return ListView.builder(
     395            0 :       itemCount: _participants.length,
     396            0 :       itemBuilder: (context, index) {
     397            0 :         final participant = _participants[index];
     398            0 :         return Card(
     399              :           margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
     400            0 :           child: ListTile(
     401            0 :             leading: CircleAvatar(
     402            0 :               backgroundColor: Colors.blue.shade100,
     403            0 :               child: Text(
     404            0 :                 participant.name?.substring(0, 1) ?? '?',
     405              :                 style: const TextStyle(color: Colors.blue),
     406              :               ),
     407              :             ),
     408            0 :             title: Text(
     409            0 :               participant.name ?? '이름 없음',
     410              :               style: const TextStyle(fontWeight: FontWeight.bold),
     411              :             ),
     412            0 :             subtitle: Row(
     413            0 :               children: [
     414              :                 // 참가 상태 뱃지
     415            0 :                 if (participant.status != null)
     416            0 :                   Container(
     417              :                     margin: const EdgeInsets.only(right: 8),
     418              :                     padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
     419            0 :                     decoration: BoxDecoration(
     420            0 :                       color: _getParticipantStatusColor(participant.status!).withOpacity(0.2),
     421            0 :                       borderRadius: BorderRadius.circular(12),
     422            0 :                       border: Border.all(color: _getParticipantStatusColor(participant.status!)),
     423              :                     ),
     424            0 :                     child: Text(
     425            0 :                       participant.status!,
     426            0 :                       style: TextStyle(
     427              :                         fontSize: 12,
     428            0 :                         color: _getParticipantStatusColor(participant.status!),
     429              :                       ),
     430              :                     ),
     431              :                   ),
     432              :                 // 결제 상태 뱃지
     433            0 :                 Container(
     434              :                   padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
     435            0 :                   decoration: BoxDecoration(
     436            0 :                     color: participant.isPaid ? Colors.green.withOpacity(0.2) : Colors.red.withOpacity(0.2),
     437            0 :                     borderRadius: BorderRadius.circular(12),
     438            0 :                     border: Border.all(color: participant.isPaid ? Colors.green : Colors.red),
     439              :                   ),
     440            0 :                   child: Text(
     441            0 :                     participant.isPaid ? '결제완료' : '미결제',
     442            0 :                     style: TextStyle(
     443              :                       fontSize: 12,
     444            0 :                       color: participant.isPaid ? Colors.green : Colors.red,
     445              :                     ),
     446              :                   ),
     447              :                 ),
     448              :               ],
     449              :             ),
     450            0 :             trailing: Row(
     451              :               mainAxisSize: MainAxisSize.min,
     452            0 :               children: [
     453            0 :                 IconButton(
     454              :                   icon: const Icon(Icons.edit, size: 20),
     455              :                   tooltip: '참가자 정보 수정',
     456            0 :                   onPressed: () => _editParticipant(participant),
     457              :                 ),
     458            0 :                 IconButton(
     459              :                   icon: const Icon(Icons.delete, size: 20),
     460              :                   tooltip: '참가자 삭제',
     461            0 :                   onPressed: () => _removeParticipant(participant),
     462              :                 ),
     463              :               ],
     464              :             ),
     465            0 :             onTap: () => _showParticipantDetails(participant),
     466              :           ),
     467              :         );
     468              :       },
     469              :     );
     470              :   }
     471              : 
     472              :   // 점수 탭
     473            0 :   Widget _buildScoresTab() {
     474            0 :     if (_scores.isEmpty) {
     475              :       return const Center(
     476              :         child: Text('등록된 점수가 없습니다.'),
     477              :       );
     478              :     }
     479              :     
     480              :     // 동점자 처리 옵션 가져오기
     481              :     List<TieBreakerOption>? tieBreakerOptions;
     482            0 :     if (_club != null && _club!.tieBreakerOptions != null && _club!.tieBreakerOptions!.isNotEmpty) {
     483            0 :       tieBreakerOptions = _club!.tieBreakerOptions;
     484              :     }
     485              :     
     486              :     // TieBreakerUtil을 사용하여 점수 정렬 및 순위 계산
     487            0 :     final sortedScores = TieBreakerUtil.sortScoresByOptions(
     488            0 :       _scores, 
     489              :       tieBreakerOptions, 
     490            0 :       _members,
     491            0 :       _includeHandicap
     492              :     );
     493              :     
     494              :     // 순위 계산
     495            0 :     final ranks = TieBreakerUtil.calculateRanks(sortedScores, _includeHandicap);
     496              :     
     497              :     // 평균 점수 계산
     498            0 :     final totalScoreSum = sortedScores.fold<int>(0, (sum, score) => 
     499            0 :       sum + ((_includeHandicap) ? score.totalScore + (score.handicap ?? 0) : score.totalScore));
     500            0 :     final averageScore = sortedScores.isNotEmpty ? totalScoreSum / sortedScores.length : 0;
     501              :     
     502            0 :     return Column(
     503            0 :       children: [
     504              :         // 핸디캡 포함 여부 토글
     505            0 :         Container(
     506              :           padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
     507            0 :           child: Row(
     508              :             mainAxisAlignment: MainAxisAlignment.center,
     509            0 :             children: [
     510              :               const Text('핸디캡 포함:', style: TextStyle(fontWeight: FontWeight.bold)),
     511            0 :               Switch(
     512            0 :                 value: _includeHandicap,
     513            0 :                 onChanged: (value) {
     514            0 :                   setState(() {
     515            0 :                     _includeHandicap = value;
     516              :                   });
     517              :                 },
     518              :                 activeColor: Colors.blue,
     519              :               ),
     520              :             ],
     521              :           ),
     522              :         ),
     523              :         
     524              :         // 평균 점수 표시
     525            0 :         Container(
     526              :           padding: const EdgeInsets.all(8),
     527              :           margin: const EdgeInsets.all(8),
     528            0 :           decoration: BoxDecoration(
     529            0 :             color: Colors.blue.shade50,
     530            0 :             borderRadius: BorderRadius.circular(8),
     531            0 :             border: Border.all(color: Colors.blue.shade200),
     532              :           ),
     533            0 :           child: Row(
     534              :             mainAxisAlignment: MainAxisAlignment.center,
     535            0 :             children: [
     536              :               const Icon(Icons.score, color: Colors.blue),
     537              :               const SizedBox(width: 8),
     538            0 :               Text(
     539            0 :                 '평균 점수: ${averageScore.toStringAsFixed(1)}',
     540              :                 style: const TextStyle(fontWeight: FontWeight.bold),
     541              :               ),
     542              :             ],
     543              :           ),
     544              :         ),
     545              :         
     546              :         // 동점자 처리 옵션 표시
     547            0 :         if (tieBreakerOptions != null && tieBreakerOptions.isNotEmpty)
     548            0 :           Container(
     549              :             padding: const EdgeInsets.all(8),
     550              :             margin: const EdgeInsets.symmetric(horizontal: 8),
     551            0 :             decoration: BoxDecoration(
     552            0 :               color: Colors.green.shade50,
     553            0 :               borderRadius: BorderRadius.circular(8),
     554            0 :               border: Border.all(color: Colors.green.shade200),
     555              :             ),
     556            0 :             child: Column(
     557              :               crossAxisAlignment: CrossAxisAlignment.start,
     558            0 :               children: [
     559              :                 const Text(
     560              :                   '동점자 처리 우선순위:',
     561              :                   style: TextStyle(fontWeight: FontWeight.bold),
     562              :                 ),
     563              :                 const SizedBox(height: 4),
     564            0 :                 Wrap(
     565              :                   spacing: 8,
     566            0 :                   children: tieBreakerOptions.map((option) {
     567              :                     String optionText = '';
     568              :                     switch (option) {
     569            0 :                       case TieBreakerOption.lowerHandicap:
     570              :                         optionText = '핸디캡 낮은 순';
     571              :                         break;
     572            0 :                       case TieBreakerOption.lowerScoreGap:
     573              :                         optionText = '점수 격차 작은 순';
     574              :                         break;
     575            0 :                       case TieBreakerOption.olderAge:
     576              :                         optionText = '연장자 우선';
     577              :                         break;
     578            0 :                       case TieBreakerOption.none:
     579              :                         optionText = '없음';
     580              :                         break;
     581              :                     }
     582            0 :                     return Chip(
     583            0 :                       label: Text(optionText),
     584            0 :                       backgroundColor: Colors.green.shade100,
     585              :                     );
     586            0 :                   }).toList(),
     587              :                 ),
     588              :               ],
     589              :             ),
     590              :           ),
     591              :         
     592              :         // 점수 목록
     593            0 :         Expanded(
     594            0 :           child: ListView.builder(
     595            0 :             itemCount: sortedScores.length,
     596            0 :             itemBuilder: (context, index) {
     597            0 :               final score = sortedScores[index];
     598            0 :               final rank = ranks[score.id] ?? (index + 1); // 동점자 처리된 순위
     599              :               
     600              :               // 참가자 이름 찾기
     601            0 :               final participant = _participants.firstWhere(
     602            0 :                 (p) => p.memberId == score.memberId,
     603            0 :                 orElse: () => Participant(
     604              :                   id: '',
     605              :                   eventId: '',
     606            0 :                   memberId: score.memberId,
     607              :                   name: '알 수 없음',
     608              :                 ),
     609              :               );
     610              :               
     611            0 :               return Card(
     612              :                 margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
     613            0 :                 child: ListTile(
     614            0 :                   leading: Stack(
     615            0 :                     children: [
     616              :                       // 배경 원
     617            0 :                       Container(
     618              :                         width: 40,
     619              :                         height: 40,
     620            0 :                         decoration: BoxDecoration(
     621            0 :                           color: _getRankColor(rank),
     622              :                           shape: BoxShape.circle,
     623              :                         ),
     624              :                       ),
     625              :                       // 순위 텍스트
     626            0 :                       Container(
     627              :                         width: 40,
     628              :                         height: 40,
     629              :                         alignment: Alignment.center,
     630            0 :                         child: Text(
     631            0 :                           rank.toString(),
     632            0 :                           key: Key('rank_${rank}_text'),
     633              :                           style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
     634              :                         ),
     635              :                       ),
     636              :                       // 테스트를 위한 추가 텍스트 (투명)
     637            0 :                       Positioned(
     638              :                         left: 0,
     639              :                         right: 0,
     640              :                         top: 0,
     641            0 :                         child: Text(
     642            0 :                           rank.toString(),
     643              :                           textAlign: TextAlign.center,
     644              :                           style: const TextStyle(color: Colors.transparent),
     645              :                         ),
     646              :                       ),
     647              :                     ],
     648              :                   ),
     649            0 :                   title: Row(
     650            0 :                     children: [
     651            0 :                       Expanded(
     652            0 :                         child: Text(
     653            0 :                           participant.name ?? '알 수 없음',
     654              :                           style: const TextStyle(fontWeight: FontWeight.bold),
     655              :                         ),
     656              :                       ),
     657            0 :                       Container(
     658              :                         padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
     659            0 :                         decoration: BoxDecoration(
     660            0 :                           color: Colors.blue.shade100,
     661            0 :                           borderRadius: BorderRadius.circular(12),
     662              :                         ),
     663            0 :                         child: Text(
     664            0 :                           _includeHandicap
     665            0 :                               ? '총점: ${score.totalScore + (score.handicap ?? 0)} (${score.totalScore}+${score.handicap ?? 0})'
     666            0 :                               : '총점: ${score.totalScore}',
     667              :                           style: const TextStyle(fontWeight: FontWeight.bold),
     668              :                         ),
     669              :                       ),
     670              :                     ],
     671              :                   ),
     672            0 :                   subtitle: Column(
     673              :                     crossAxisAlignment: CrossAxisAlignment.start,
     674            0 :                     children: [
     675              :                       const SizedBox(height: 4),
     676            0 :                       Text(
     677            0 :                         '날짜: ${DateFormat('yyyy-MM-dd').format(score.date)}',
     678              :                       ),
     679              :                       const SizedBox(height: 4),
     680            0 :                       SingleChildScrollView(
     681              :                         scrollDirection: Axis.horizontal,
     682            0 :                         child: Row(
     683            0 :                           children: score.frames.asMap().entries.map((entry) {
     684            0 :                             return Container(
     685              :                               width: 30,
     686              :                               height: 30,
     687              :                               margin: const EdgeInsets.only(right: 4),
     688            0 :                               decoration: BoxDecoration(
     689            0 :                                 color: _getScoreColor(entry.value),
     690            0 :                                 borderRadius: BorderRadius.circular(4),
     691              :                               ),
     692            0 :                               child: Center(
     693            0 :                                 child: Text(
     694              :                                   // 스트라이크는 'X'로, 스페어는 '/'로 표시
     695            0 :                                   _getFrameDisplay(entry.key, entry.value, score.frames),
     696              :                                   style: const TextStyle(
     697              :                                     color: Colors.white,
     698              :                                     fontWeight: FontWeight.bold,
     699              :                                   ),
     700              :                                 ),
     701              :                               ),
     702              :                             );
     703            0 :                           }).toList(),
     704              :                         ),
     705              :                       ),
     706              :                     ],
     707              :                   ),
     708            0 :                   trailing: Row(
     709              :                     mainAxisSize: MainAxisSize.min,
     710            0 :                     children: [
     711            0 :                       IconButton(
     712              :                         icon: const Icon(Icons.edit, size: 20),
     713              :                         tooltip: '점수 수정',
     714            0 :                         onPressed: () => _editScore(score),
     715              :                       ),
     716            0 :                       IconButton(
     717              :                         icon: const Icon(Icons.delete, size: 20),
     718              :                         tooltip: '점수 삭제',
     719            0 :                         onPressed: () => _deleteScore(score),
     720              :                       ),
     721              :                     ],
     722              :                   ),
     723            0 :                   onTap: () => _showScoreDetails(score),
     724              :                 ),
     725              :               );
     726              :             },
     727              :           ),
     728              :         ),
     729              :       ],
     730              :     );
     731              :   }
     732              : 
     733              :   // 팀 탭
     734            0 :   Widget _buildTeamsTab() {
     735            0 :     if (_teams.isEmpty) {
     736            0 :       return Center(
     737            0 :         child: Padding(
     738              :           padding: const EdgeInsets.all(16.0),
     739            0 :           child: Column(
     740              :             mainAxisAlignment: MainAxisAlignment.center,
     741            0 :             children: [
     742              :               const Icon(Icons.groups, size: 64, color: Colors.blue),
     743              :               const SizedBox(height: 16),
     744              :               const Text('생성된 팀이 없습니다.', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
     745              :               const SizedBox(height: 24),
     746              :               // 팀 생성 옵션
     747            0 :               Card(
     748            0 :                 child: Padding(
     749              :                   padding: const EdgeInsets.all(16.0),
     750            0 :                   child: Column(
     751              :                     crossAxisAlignment: CrossAxisAlignment.start,
     752            0 :                     children: [
     753              :                       const Text('팀 생성 옵션', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
     754              :                       const SizedBox(height: 16),
     755              :                       // 팀 생성 방법 선택
     756            0 :                       Row(
     757            0 :                         children: [
     758            0 :                           Radio<int>(
     759              :                             value: 1,
     760            0 :                             groupValue: _teamGenerationMethod,
     761            0 :                             onChanged: (value) {
     762            0 :                               setState(() {
     763            0 :                                 _teamGenerationMethod = value!;
     764              :                               });
     765              :                             },
     766              :                           ),
     767              :                           const Text('팀 인원수로 나누기'),
     768              :                         ],
     769              :                       ),
     770            0 :                       if (_teamGenerationMethod == 1)
     771            0 :                         Padding(
     772              :                           padding: const EdgeInsets.only(left: 32.0),
     773            0 :                           child: Row(
     774            0 :                             children: [
     775            0 :                               SizedBox(
     776              :                                 width: 80,
     777            0 :                                 child: TextFormField(
     778            0 :                                   controller: _teamSizeController,
     779              :                                   decoration: const InputDecoration(
     780              :                                     labelText: '인원수',
     781              :                                     suffixText: '명',
     782              :                                   ),
     783              :                                   keyboardType: TextInputType.number,
     784            0 :                                   inputFormatters: [FilteringTextInputFormatter.digitsOnly],
     785              :                                 ),
     786              :                               ),
     787              :                               const SizedBox(width: 16),
     788            0 :                               Text('총 ${_participants.length}명 참가자'),
     789              :                             ],
     790              :                           ),
     791              :                         ),
     792            0 :                       const SizedBox(height: 8),
     793            0 :                       Row(
     794            0 :                         children: [
     795            0 :                           Radio<int>(
     796              :                             value: 2,
     797            0 :                             groupValue: _teamGenerationMethod,
     798            0 :                             onChanged: (value) {
     799            0 :                               setState(() {
     800            0 :                                 _teamGenerationMethod = value!;
     801              :                               });
     802              :                             },
     803              :                           ),
     804              :                           const Text('팀 개수로 나누기'),
     805              :                         ],
     806              :                       ),
     807            0 :                       if (_teamGenerationMethod == 2)
     808            0 :                         Padding(
     809              :                           padding: const EdgeInsets.only(left: 32.0),
     810            0 :                           child: Row(
     811            0 :                             children: [
     812            0 :                               SizedBox(
     813              :                                 width: 80,
     814            0 :                                 child: TextFormField(
     815            0 :                                   controller: _teamCountController,
     816              :                                   decoration: const InputDecoration(
     817              :                                     labelText: '팀 수',
     818              :                                     suffixText: '개',
     819              :                                   ),
     820              :                                   keyboardType: TextInputType.number,
     821            0 :                                   inputFormatters: [FilteringTextInputFormatter.digitsOnly],
     822              :                                 ),
     823              :                               ),
     824              :                               const SizedBox(width: 16),
     825            0 :                               Text('총 ${_participants.length}명 참가자'),
     826              :                             ],
     827              :                           ),
     828              :                         ),
     829            0 :                       const SizedBox(height: 16),
     830              :                       // 팀 생성 버튼
     831            0 :                       Row(
     832              :                         mainAxisAlignment: MainAxisAlignment.center,
     833            0 :                         children: [
     834            0 :                           ElevatedButton.icon(
     835            0 :                             onPressed: _generateTeams,
     836              :                             icon: const Icon(Icons.group_add),
     837              :                             label: const Text('팀 생성하기'),
     838            0 :                             style: ElevatedButton.styleFrom(
     839              :                               backgroundColor: Colors.blue,
     840              :                               foregroundColor: Colors.white,
     841              :                               padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
     842              :                             ),
     843              :                           ),
     844              :                         ],
     845              :                       ),
     846              :                     ],
     847              :                   ),
     848              :                 ),
     849              :               ),
     850              :             ],
     851              :           ),
     852              :         ),
     853              :       );
     854              :     }
     855              :     
     856              :     // 미배정 참가자 목록 조회
     857            0 :     final List<Participant> unassignedParticipants = _getUnassignedParticipants();
     858              :     
     859            0 :     return Column(
     860            0 :       children: [
     861              :         // 팀 관리 버튼
     862            0 :         Padding(
     863              :           padding: const EdgeInsets.all(8.0),
     864            0 :           child: Row(
     865              :             mainAxisAlignment: MainAxisAlignment.spaceEvenly,
     866            0 :             children: [
     867            0 :               ElevatedButton.icon(
     868            0 :                 onPressed: _generateTeams,
     869              :                 icon: const Icon(Icons.refresh),
     870              :                 label: const Text('팀 재생성'),
     871            0 :                 style: ElevatedButton.styleFrom(
     872              :                   backgroundColor: Colors.blue,
     873              :                   foregroundColor: Colors.white,
     874              :                 ),
     875              :               ),
     876            0 :               ElevatedButton.icon(
     877            0 :                 onPressed: _saveTeams,
     878              :                 icon: const Icon(Icons.save),
     879              :                 label: const Text('팀 저장'),
     880            0 :                 style: ElevatedButton.styleFrom(
     881              :                   backgroundColor: Colors.green,
     882              :                   foregroundColor: Colors.white,
     883              :                 ),
     884              :               ),
     885              :             ],
     886              :           ),
     887              :         ),
     888              :         
     889              :         // 이벤트 설명
     890            0 :         if (widget.event.description != null && widget.event.description!.isNotEmpty)
     891            0 :           Padding(
     892              :             padding: const EdgeInsets.symmetric(vertical: 16.0),
     893            0 :             child: Column(
     894              :               crossAxisAlignment: CrossAxisAlignment.start,
     895            0 :               children: [
     896              :                 const Text(
     897              :                   '이벤트 설명',
     898              :                   style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
     899              :                 ),
     900              :                 const SizedBox(height: 8),
     901            0 :                 Text(widget.event.description!),
     902              :               ],
     903              :             ),
     904              :           ),
     905              : 
     906              :         // 공유 버튼
     907            0 :         Padding(
     908              :           padding: const EdgeInsets.symmetric(vertical: 16.0),
     909            0 :           child: ElevatedButton.icon(
     910            0 :             onPressed: _shareEvent,
     911              :             icon: const Icon(Icons.share),
     912              :             label: const Text('이벤트 공유'),
     913            0 :             style: ElevatedButton.styleFrom(
     914              :               foregroundColor: Colors.white,
     915              :               backgroundColor: Colors.blue,
     916              :             ),
     917              :           ),
     918              :         ),
     919              :         
     920              :         // 미배정 참가자 섹션
     921            0 :         if (unassignedParticipants.isNotEmpty)
     922            0 :           Card(
     923              :             margin: const EdgeInsets.all(8),
     924            0 :             color: Colors.amber.shade50,
     925            0 :             child: Column(
     926              :               crossAxisAlignment: CrossAxisAlignment.start,
     927            0 :               children: [
     928            0 :                 Padding(
     929              :                   padding: const EdgeInsets.all(8.0),
     930            0 :                   child: Row(
     931            0 :                     children: [
     932              :                       const Icon(Icons.person_off, color: Colors.amber),
     933              :                       const SizedBox(width: 8),
     934            0 :                       Text('미배정 참가자 (${unassignedParticipants.length}명)', 
     935              :                         style: const TextStyle(fontWeight: FontWeight.bold),
     936              :                       ),
     937              :                     ],
     938              :                   ),
     939              :                 ),
     940              :                 const Divider(height: 1),
     941            0 :                 Wrap(
     942            0 :                   children: unassignedParticipants.map((participant) {
     943            0 :                     return Padding(
     944              :                       padding: const EdgeInsets.all(4.0),
     945            0 :                       child: Chip(
     946              :                         avatar: const CircleAvatar(
     947              :                           child: Icon(Icons.person, size: 16),
     948              :                         ),
     949            0 :                         label: Text(participant.name ?? '알 수 없음'),
     950              :                         deleteIcon: const Icon(Icons.add_circle, size: 18),
     951            0 :                         onDeleted: () => _showTeamSelectionDialog(participant),
     952              :                       ),
     953              :                     );
     954            0 :                   }).toList(),
     955              :                 ),
     956              :               ],
     957              :             ),
     958              :           ),
     959              :         
     960              :         // 팀 목록
     961            0 :         Expanded(
     962            0 :           child: ListView.builder(
     963            0 :             itemCount: _teams.length,
     964            0 :             itemBuilder: (context, index) {
     965            0 :               final team = _teams[index];
     966            0 :               final teamMembers = _getTeamMembers(team);
     967            0 :               final teamAverage = _calculateTeamAverage(team);
     968              :               
     969            0 :               return Card(
     970              :                 margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
     971            0 :                 child: ExpansionTile(
     972            0 :                   leading: CircleAvatar(
     973            0 :                     backgroundColor: Colors.blue.shade700,
     974            0 :                     child: Text('${index + 1}', style: const TextStyle(color: Colors.white)),
     975              :                   ),
     976            0 :                   title: Row(
     977            0 :                     children: [
     978            0 :                       Text('팀 ${team.name}', style: const TextStyle(fontWeight: FontWeight.bold)),
     979              :                       const SizedBox(width: 8),
     980            0 :                       Container(
     981              :                         padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
     982            0 :                         decoration: BoxDecoration(
     983            0 :                           color: Colors.blue.shade100,
     984            0 :                           borderRadius: BorderRadius.circular(12),
     985              :                         ),
     986            0 :                         child: Text('${team.memberIds.length}명'),
     987              :                       ),
     988              :                     ],
     989              :                   ),
     990            0 :                   subtitle: Row(
     991            0 :                     children: [
     992              :                       const Icon(Icons.bar_chart, size: 16, color: Colors.blue),
     993              :                       const SizedBox(width: 4),
     994            0 :                       Text('팀 에버리지: ${teamAverage.toStringAsFixed(1)}'),
     995              :                     ],
     996              :                   ),
     997            0 :                   children: [
     998            0 :                     ...teamMembers.map((participant) {
     999              :                       // 참가자의 평균 점수 계산
    1000            0 :                       final participantScores = _scores.where((s) => s.memberId == participant.memberId).toList();
    1001            0 :                       final participantAverage = participantScores.isNotEmpty
    1002            0 :                           ? participantScores.fold<int>(0, (sum, s) => sum + s.totalScore) / participantScores.length
    1003              :                           : 0.0;
    1004              :                       
    1005            0 :                       return ListTile(
    1006              :                         leading: const CircleAvatar(
    1007              :                           child: Icon(Icons.person, size: 16),
    1008              :                         ),
    1009            0 :                         title: Text(participant.name ?? '알 수 없음'),
    1010            0 :                         subtitle: Text('평균: ${participantAverage.toStringAsFixed(1)}'),
    1011            0 :                         trailing: IconButton(
    1012              :                           icon: const Icon(Icons.remove_circle, color: Colors.red),
    1013              :                           tooltip: '팀에서 제외',
    1014            0 :                           onPressed: () => _removeFromTeam(team, participant),
    1015              :                         ),
    1016              :                       );
    1017            0 :                     }).toList(),
    1018              :                     // 팀원 추가 버튼
    1019            0 :                     if (unassignedParticipants.isNotEmpty)
    1020            0 :                       ListTile(
    1021              :                         leading: const Icon(Icons.add_circle, color: Colors.green),
    1022              :                         title: const Text('팀원 추가하기'),
    1023            0 :                         onTap: () => _showParticipantSelectionDialog(team),
    1024              :                       ),
    1025              :                   ],
    1026              :                 ),
    1027              :               );
    1028              :             },
    1029              :           ),
    1030              :         ),
    1031              :       ],
    1032              :     );
    1033              :   }
    1034              : 
    1035              :   // 정보 행 위젯
    1036            0 :   Widget _buildInfoRow(IconData icon, String text, {bool isSelectable = false}) {
    1037            0 :     return Padding(
    1038              :       padding: const EdgeInsets.symmetric(vertical: 8.0),
    1039            0 :       child: Row(
    1040            0 :         children: [
    1041            0 :           Icon(icon, color: Colors.blue),
    1042              :           const SizedBox(width: 8),
    1043              :           isSelectable
    1044            0 :               ? Expanded(
    1045            0 :                   child: SelectableText(
    1046              :                     text,
    1047              :                     style: const TextStyle(fontSize: 16),
    1048              :                   ),
    1049              :                 )
    1050            0 :               : Expanded(
    1051            0 :                   child: Text(
    1052              :                     text,
    1053              :                     style: const TextStyle(fontSize: 16),
    1054              :                   ),
    1055              :                 ),
    1056              :         ],
    1057              :       ),
    1058              :     );
    1059              :   }
    1060              : 
    1061              :   // 이벤트 유형에 따른 색상 반환
    1062            0 :   Color _getTypeColor(String type) {
    1063            0 :     switch (type.toLowerCase()) {
    1064            0 :       case '개인전':
    1065            0 :       case 'individual':
    1066              :         return Colors.blue;
    1067            0 :       case '팀전':
    1068            0 :       case 'team':
    1069              :         return Colors.purple;
    1070            0 :       case '리그':
    1071            0 :       case 'league':
    1072              :         return Colors.green;
    1073            0 :       case '토너먼트':
    1074            0 :       case 'tournament':
    1075              :         return Colors.orange;
    1076              :       default:
    1077              :         return Colors.grey;
    1078              :     }
    1079              :   }
    1080              : 
    1081              :   // 이벤트 상태에 따른 색상 반환
    1082            0 :   Color _getStatusColor(String status) {
    1083            0 :     switch (status.toLowerCase()) {
    1084            0 :       case '활성':
    1085            0 :       case 'active':
    1086              :         return Colors.green;
    1087            0 :       case '대기':
    1088            0 :       case 'pending':
    1089              :         return Colors.orange;
    1090            0 :       case '취소':
    1091            0 :       case 'cancelled':
    1092              :         return Colors.red;
    1093            0 :       case '완료':
    1094            0 :       case 'completed':
    1095              :         return Colors.blue;
    1096              :       default:
    1097              :         return Colors.grey;
    1098              :     }
    1099              :   }
    1100              :   
    1101              :   // 참가자 상태에 따른 색상 반환
    1102            0 :   Color _getParticipantStatusColor(String status) {
    1103            0 :     switch (status.toLowerCase()) {
    1104            0 :       case 'registered':
    1105            0 :       case '등록됨':
    1106              :         return Colors.blue;
    1107            0 :       case 'confirmed':
    1108            0 :       case '확인됨':
    1109              :         return Colors.green;
    1110            0 :       case 'cancelled':
    1111            0 :       case '취소됨':
    1112              :         return Colors.red;
    1113            0 :       case 'attended':
    1114            0 :       case '참석함':
    1115              :         return Colors.purple;
    1116              :       default:
    1117              :         return Colors.grey;
    1118              :     }
    1119              :   }
    1120              :   
    1121              :   // 순위에 따른 색상 반환
    1122            0 :   Color _getRankColor(int rank) {
    1123              :     switch (rank) {
    1124            0 :       case 1:
    1125            0 :         return Colors.amber.shade700; // 금메달
    1126            0 :       case 2:
    1127            0 :         return Colors.blueGrey.shade400; // 은메달
    1128            0 :       case 3:
    1129            0 :         return Colors.brown.shade400; // 동메달
    1130              :       default:
    1131            0 :         return Colors.blue.shade700; // 기본 색상
    1132              :     }
    1133              :   }
    1134              :   
    1135              :   // 점수에 따른 색상 반환
    1136            0 :   Color _getScoreColor(int score) {
    1137            0 :     if (score == 10) {
    1138            0 :       return Colors.red.shade700; // 스트라이크
    1139            0 :     } else if (score >= 7) {
    1140            0 :       return Colors.orange.shade700; // 좋은 점수
    1141            0 :     } else if (score >= 5) {
    1142            0 :       return Colors.green.shade700; // 평균 점수
    1143              :     } else {
    1144            0 :       return Colors.blue.shade700; // 낮은 점수
    1145              :     }
    1146              :   }
    1147              :   
    1148              :   // 프레임 표시 문자열 반환
    1149            0 :   String _getFrameDisplay(int frameIndex, int score, List<int> frames) {
    1150              :     // 스트라이크 표시
    1151            0 :     if (score == 10) {
    1152              :       return 'X';
    1153              :     }
    1154              :     
    1155              :     // 스페어 표시 (이전 프레임과 합쳐서 10점이면 스페어)
    1156            0 :     if (frameIndex > 0 && frames[frameIndex - 1] + score == 10) {
    1157              :       return '/';
    1158              :     }
    1159              :     
    1160              :     // 일반 점수 표시
    1161            0 :     return score.toString();
    1162              :   }
    1163              :   
    1164              :   // 미배정 참가자 목록 가져오기
    1165            0 :   List<Participant> _getUnassignedParticipants() {
    1166              :     // 현재 팀에 배정된 모든 참가자 ID 목록
    1167            0 :     final List<String> assignedMemberIds = [];
    1168            0 :     for (final team in _teams) {
    1169            0 :       assignedMemberIds.addAll(team.memberIds);
    1170              :     }
    1171              :     
    1172              :     // 배정되지 않은 참가자 목록 반환
    1173            0 :     return _participants.where((p) => !assignedMemberIds.contains(p.memberId)).toList();
    1174              :   }
    1175              :   
    1176              :   // 팀원 목록 가져오기
    1177            0 :   List<Participant> _getTeamMembers(Team team) {
    1178            0 :     return _participants
    1179            0 :         .where((p) => team.memberIds.contains(p.memberId))
    1180            0 :         .toList();
    1181              :   }
    1182              :   
    1183              :   // 팀 평균 점수 계산
    1184            0 :   double _calculateTeamAverage(Team team) {
    1185            0 :     if (team.memberIds.isEmpty) return 0.0;
    1186              :     
    1187              :     double totalAverage = 0.0;
    1188              :     int memberCount = 0;
    1189              :     
    1190            0 :     for (final memberId in team.memberIds) {
    1191            0 :       final memberScores = _scores.where((s) => s.memberId == memberId).toList();
    1192            0 :       if (memberScores.isNotEmpty) {
    1193            0 :         final memberTotal = memberScores.fold<int>(0, (sum, score) => sum + score.totalScore);
    1194            0 :         totalAverage += memberTotal / memberScores.length;
    1195            0 :         memberCount++;
    1196              :       }
    1197              :     }
    1198              :     
    1199            0 :     return memberCount > 0 ? totalAverage / memberCount : 0.0;
    1200              :   }
    1201              :   
    1202              :   // 팀 생성 방법
    1203            0 :   void _generateTeams() {
    1204            0 :     if (_participants.isEmpty) {
    1205            0 :       ScaffoldMessenger.of(context).showSnackBar(
    1206              :         const SnackBar(content: Text('참가자가 없습니다.')),
    1207              :       );
    1208              :       return;
    1209              :     }
    1210              :     
    1211              :     // 기존 팀 삭제
    1212            0 :     setState(() {
    1213            0 :       _teams.clear();
    1214              :     });
    1215              :     
    1216              :     // 참가자 셔플
    1217            0 :     final shuffledParticipants = List<Participant>.from(_participants);
    1218            0 :     shuffledParticipants.shuffle();
    1219              :     
    1220              :     int teamCount;
    1221              :     int teamSize;
    1222              :     
    1223              :     // 팀 생성 방법에 따른 팀 개수 계산
    1224            0 :     if (_teamGenerationMethod == 1) {
    1225              :       // 팀 인원수로 나누기
    1226            0 :       teamSize = int.tryParse(_teamSizeController.text) ?? 4;
    1227            0 :       if (teamSize <= 0) teamSize = 4;
    1228            0 :       teamCount = (_participants.length / teamSize).ceil();
    1229              :     } else {
    1230              :       // 팀 개수로 나누기
    1231            0 :       teamCount = int.tryParse(_teamCountController.text) ?? 2;
    1232            0 :       if (teamCount <= 0) teamCount = 2;
    1233            0 :       teamSize = (_participants.length / teamCount).ceil();
    1234              :     }
    1235              :     
    1236              :     // 팀 생성
    1237            0 :     final List<Team> newTeams = [];
    1238            0 :     for (int i = 0; i < teamCount; i++) {
    1239            0 :       final teamName = String.fromCharCode(65 + i); // A, B, C, ...
    1240            0 :       final team = Team(
    1241            0 :         id: 'temp_${DateTime.now().millisecondsSinceEpoch}_$i',
    1242            0 :         eventId: widget.event.id,
    1243              :         name: teamName,
    1244            0 :         memberIds: [],
    1245              :       );
    1246            0 :       newTeams.add(team);
    1247              :     }
    1248              :     
    1249              :     // 참가자 배정
    1250            0 :     for (int i = 0; i < shuffledParticipants.length; i++) {
    1251            0 :       final teamIndex = i % teamCount;
    1252            0 :       final memberId = shuffledParticipants[i].memberId;
    1253            0 :       newTeams[teamIndex].memberIds.add(memberId);
    1254              :     }
    1255              :     
    1256            0 :     setState(() {
    1257            0 :       _teams = newTeams;
    1258              :     });
    1259              :     
    1260            0 :     ScaffoldMessenger.of(context).showSnackBar(
    1261            0 :       SnackBar(content: Text('팀이 생성되었습니다. ($teamCount개 팀)')),
    1262              :     );
    1263              :   }
    1264              :   
    1265              :   // 팀 저장
    1266            0 :   void _saveTeams() async {
    1267            0 :     if (_teams.isEmpty) {
    1268            0 :       ScaffoldMessenger.of(context).showSnackBar(
    1269              :         const SnackBar(content: Text('저장할 팀이 없습니다.')),
    1270              :       );
    1271              :       return;
    1272              :     }
    1273              :     
    1274            0 :     setState(() {
    1275            0 :       _isLoading = true;
    1276              :     });
    1277              :     
    1278              :     try {
    1279              :       // 기존 팀 삭제 및 새 팀 저장 로직 구현
    1280              :       // TODO: API 연동 구현
    1281              :       
    1282            0 :       ScaffoldMessenger.of(context).showSnackBar(
    1283              :         const SnackBar(content: Text('팀이 저장되었습니다.')),
    1284              :       );
    1285              :     } catch (e) {
    1286            0 :       ScaffoldMessenger.of(context).showSnackBar(
    1287            0 :         SnackBar(content: Text('팀 저장 중 오류가 발생했습니다: $e')),
    1288              :       );
    1289              :     } finally {
    1290            0 :       setState(() {
    1291            0 :         _isLoading = false;
    1292              :       });
    1293              :     }
    1294              :   }
    1295              :   
    1296              :   // 팀에서 참가자 제거
    1297            0 :   void _removeFromTeam(Team team, Participant participant) {
    1298            0 :     setState(() {
    1299            0 :       team.memberIds.remove(participant.memberId);
    1300              :     });
    1301              :     
    1302            0 :     ScaffoldMessenger.of(context).showSnackBar(
    1303            0 :       SnackBar(content: Text('${participant.name}님이 팀에서 제외되었습니다.')),
    1304              :     );
    1305              :   }
    1306              :   
    1307              :   // 참가자 선택 다이얼로그 표시
    1308            0 :   void _showParticipantSelectionDialog(Team team) {
    1309            0 :     final unassignedParticipants = _getUnassignedParticipants();
    1310            0 :     if (unassignedParticipants.isEmpty) {
    1311            0 :       ScaffoldMessenger.of(context).showSnackBar(
    1312              :         const SnackBar(content: Text('추가할 참가자가 없습니다.')),
    1313              :       );
    1314              :       return;
    1315              :     }
    1316              :     
    1317            0 :     showDialog(
    1318            0 :       context: context,
    1319            0 :       builder: (context) => AlertDialog(
    1320            0 :         title: Text('팀 ${team.name}에 참가자 추가'),
    1321            0 :         content: SizedBox(
    1322              :           width: double.maxFinite,
    1323            0 :           child: ListView.builder(
    1324              :             shrinkWrap: true,
    1325            0 :             itemCount: unassignedParticipants.length,
    1326            0 :             itemBuilder: (context, index) {
    1327            0 :               final participant = unassignedParticipants[index];
    1328            0 :               return ListTile(
    1329              :                 leading: const CircleAvatar(
    1330              :                   child: Icon(Icons.person, size: 16),
    1331              :                 ),
    1332            0 :                 title: Text(participant.name ?? '알 수 없음'),
    1333            0 :                 onTap: () {
    1334            0 :                   Navigator.of(context).pop();
    1335            0 :                   setState(() {
    1336            0 :                     team.memberIds.add(participant.memberId);
    1337              :                   });
    1338            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1339            0 :                     SnackBar(content: Text('${participant.name}님이 팀 ${team.name}에 추가되었습니다.')),
    1340              :                   );
    1341              :                 },
    1342              :               );
    1343              :             },
    1344              :           ),
    1345              :         ),
    1346            0 :         actions: [
    1347            0 :           TextButton(
    1348            0 :             onPressed: () => Navigator.of(context).pop(),
    1349              :             child: const Text('취소'),
    1350              :           ),
    1351              :         ],
    1352              :       ),
    1353              :     );
    1354              :   }
    1355              :   
    1356              :   // 참가자를 추가할 팀 선택 다이얼로그 표시
    1357            0 :   void _showTeamSelectionDialog(Participant participant) {
    1358            0 :     if (_teams.isEmpty) {
    1359            0 :       ScaffoldMessenger.of(context).showSnackBar(
    1360              :         const SnackBar(content: Text('추가할 팀이 없습니다.')),
    1361              :       );
    1362              :       return;
    1363              :     }
    1364              :     
    1365            0 :     showDialog(
    1366            0 :       context: context,
    1367            0 :       builder: (context) => AlertDialog(
    1368            0 :         title: Text('${participant.name}님을 추가할 팀 선택'),
    1369            0 :         content: SizedBox(
    1370              :           width: double.maxFinite,
    1371            0 :           child: ListView.builder(
    1372              :             shrinkWrap: true,
    1373            0 :             itemCount: _teams.length,
    1374            0 :             itemBuilder: (context, index) {
    1375            0 :               final team = _teams[index];
    1376            0 :               return ListTile(
    1377            0 :                 leading: CircleAvatar(
    1378            0 :                   backgroundColor: Colors.blue.shade700,
    1379            0 :                   child: Text('${index + 1}', style: const TextStyle(color: Colors.white)),
    1380              :                 ),
    1381            0 :                 title: Text('팀 ${team.name} (${team.memberIds.length}명)'),
    1382            0 :                 onTap: () {
    1383            0 :                   Navigator.of(context).pop();
    1384            0 :                   setState(() {
    1385            0 :                     team.memberIds.add(participant.memberId);
    1386              :                   });
    1387            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1388            0 :                     SnackBar(content: Text('${participant.name}님이 팀 ${team.name}에 추가되었습니다.')),
    1389              :                   );
    1390              :                 },
    1391              :               );
    1392              :             },
    1393              :           ),
    1394              :         ),
    1395            0 :         actions: [
    1396            0 :           TextButton(
    1397            0 :             onPressed: () => Navigator.of(context).pop(),
    1398              :             child: const Text('취소'),
    1399              :           ),
    1400              :         ],
    1401              :       ),
    1402              :     );
    1403              :   }
    1404              : 
    1405              :   // 이벤트 수정
    1406            0 :   void _editEvent() {
    1407              :     // 이벤트 수정 다이얼로그 또는 화면으로 이동
    1408            0 :     Navigator.of(context).pop(true); // 수정을 위해 이전 화면으로 돌아가기
    1409              :   }
    1410              : 
    1411              :   // 참가자 추가
    1412            0 :   void _addParticipant() {
    1413              :     // 참가자 추가 다이얼로그 표시
    1414            0 :     showDialog(
    1415            0 :       context: context,
    1416            0 :       builder: (context) => AlertDialog(
    1417              :         title: const Text('참가자 추가'),
    1418              :         content: const Text('참가자 추가 기능은 아직 구현 중입니다.'),
    1419            0 :         actions: [
    1420            0 :           TextButton(
    1421            0 :             onPressed: () => Navigator.of(context).pop(),
    1422              :             child: const Text('확인'),
    1423              :           ),
    1424              :         ],
    1425              :       ),
    1426              :     );
    1427              :   }
    1428              : 
    1429              :   // 참가자 수정
    1430            0 :   void _editParticipant(Participant participant) {
    1431              :     // 참가자 수정 다이얼로그 표시
    1432            0 :     showDialog(
    1433            0 :       context: context,
    1434            0 :       builder: (context) => AlertDialog(
    1435              :         title: const Text('참가자 수정'),
    1436            0 :         content: Text('${participant.name} 참가자 수정 기능은 아직 구현 중입니다.'),
    1437            0 :         actions: [
    1438            0 :           TextButton(
    1439            0 :             onPressed: () => Navigator.of(context).pop(),
    1440              :             child: const Text('확인'),
    1441              :           ),
    1442              :         ],
    1443              :       ),
    1444              :     );
    1445              :   }
    1446              : 
    1447              :   // 참가자 삭제
    1448            0 :   void _removeParticipant(Participant participant) {
    1449              :     // 참가자 삭제 확인 다이얼로그
    1450            0 :     showDialog(
    1451            0 :       context: context,
    1452            0 :       builder: (context) => AlertDialog(
    1453              :         title: const Text('참가자 삭제'),
    1454            0 :         content: Text('${participant.name} 참가자를 정말 삭제하시겠습니까?'),
    1455            0 :         actions: [
    1456            0 :           TextButton(
    1457            0 :             onPressed: () => Navigator.of(context).pop(),
    1458              :             child: const Text('취소'),
    1459              :           ),
    1460            0 :           TextButton(
    1461            0 :             onPressed: () async {
    1462            0 :               Navigator.of(context).pop();
    1463              :               
    1464            0 :               setState(() {
    1465            0 :                 _isLoading = true;
    1466              :               });
    1467              :               
    1468              :               try {
    1469            0 :                 final eventService = Provider.of<EventService>(context, listen: false);
    1470            0 :                 await eventService.removeParticipant(widget.event.id, participant.id);
    1471              :                 
    1472            0 :                 if (mounted) {
    1473            0 :                   setState(() {
    1474            0 :                     _participants.removeWhere((p) => p.id == participant.id);
    1475            0 :                     _isLoading = false;
    1476              :                   });
    1477              :                   
    1478            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1479              :                     const SnackBar(content: Text('참가자가 삭제되었습니다')),
    1480              :                   );
    1481              :                 }
    1482              :               } catch (e) {
    1483            0 :                 if (mounted) {
    1484            0 :                   setState(() {
    1485            0 :                     _isLoading = false;
    1486              :                   });
    1487              :                   
    1488            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1489            0 :                     SnackBar(content: Text('참가자 삭제에 실패했습니다: $e')),
    1490              :                   );
    1491              :                 }
    1492              :               }
    1493              :             },
    1494            0 :             style: TextButton.styleFrom(foregroundColor: Colors.red),
    1495              :             child: const Text('삭제'),
    1496              :           ),
    1497              :         ],
    1498              :       ),
    1499              :     );
    1500              :   }
    1501              : 
    1502              :   // 참가자 상세 정보 표시
    1503            0 :   void _showParticipantDetails(Participant participant) {
    1504              :     // 참가자 상세 정보 다이얼로그
    1505            0 :     showDialog(
    1506            0 :       context: context,
    1507            0 :       builder: (context) => AlertDialog(
    1508            0 :         title: Text(participant.name ?? '이름 없음'),
    1509            0 :         content: Column(
    1510              :           mainAxisSize: MainAxisSize.min,
    1511              :           crossAxisAlignment: CrossAxisAlignment.start,
    1512            0 :           children: [
    1513            0 :             if (participant.email != null)
    1514            0 :               _buildInfoRow(Icons.email, participant.email!),
    1515            0 :             if (participant.phoneNumber != null)
    1516            0 :               _buildInfoRow(Icons.phone, participant.phoneNumber!),
    1517            0 :             _buildInfoRow(Icons.info, '상태: ${participant.status ?? "없음"}'),
    1518            0 :             _buildInfoRow(
    1519              :               Icons.payment,
    1520            0 :               '결제: ${participant.isPaid ? "완료" : "미완료"}${participant.paidAmount != null ? " (${participant.paidAmount}원)" : ""}',
    1521              :             ),
    1522            0 :             if (participant.notes != null) ...[
    1523              :               const Divider(),
    1524              :               const Text('메모:', style: TextStyle(fontWeight: FontWeight.bold)),
    1525            0 :               Text(participant.notes!),
    1526              :             ],
    1527              :           ],
    1528              :         ),
    1529            0 :         actions: [
    1530            0 :           TextButton(
    1531            0 :             onPressed: () => Navigator.of(context).pop(),
    1532              :             child: const Text('닫기'),
    1533              :           ),
    1534              :         ],
    1535              :       ),
    1536              :     );
    1537              :   }
    1538              : 
    1539              :   // 점수 추가
    1540            0 :   void _addScore() {
    1541              :     // 점수 추가 다이얼로그 표시
    1542            0 :     showDialog(
    1543            0 :       context: context,
    1544            0 :       builder: (context) => AlertDialog(
    1545              :         title: const Text('점수 추가'),
    1546              :         content: const Text('점수 추가 기능은 아직 구현 중입니다.'),
    1547            0 :         actions: [
    1548            0 :           TextButton(
    1549            0 :             onPressed: () => Navigator.of(context).pop(),
    1550              :             child: const Text('확인'),
    1551              :           ),
    1552              :         ],
    1553              :       ),
    1554              :     );
    1555              :   }
    1556              : 
    1557              :   // 점수 수정
    1558            0 :   void _editScore(Score score) {
    1559              :     // 점수 수정 다이얼로그 표시
    1560            0 :     showDialog(
    1561            0 :       context: context,
    1562            0 :       builder: (context) => AlertDialog(
    1563              :         title: const Text('점수 수정'),
    1564            0 :         content: Text('점수 ID: ${score.id} 수정 기능은 아직 구현 중입니다.'),
    1565            0 :         actions: [
    1566            0 :           TextButton(
    1567            0 :             onPressed: () => Navigator.of(context).pop(),
    1568              :             child: const Text('확인'),
    1569              :           ),
    1570              :         ],
    1571              :       ),
    1572              :     );
    1573              :   }
    1574              : 
    1575              :   // 점수 삭제
    1576            0 :   void _deleteScore(Score score) {
    1577              :     // 점수 삭제 확인 다이얼로그
    1578            0 :     showDialog(
    1579            0 :       context: context,
    1580            0 :       builder: (context) => AlertDialog(
    1581              :         title: const Text('점수 삭제'),
    1582              :         content: const Text('이 점수를 정말 삭제하시겠습니까?'),
    1583            0 :         actions: [
    1584            0 :           TextButton(
    1585            0 :             onPressed: () => Navigator.of(context).pop(),
    1586              :             child: const Text('취소'),
    1587              :           ),
    1588            0 :           TextButton(
    1589            0 :             onPressed: () async {
    1590            0 :               Navigator.of(context).pop();
    1591              :               
    1592            0 :               setState(() {
    1593            0 :                 _isLoading = true;
    1594              :               });
    1595              :               
    1596              :               try {
    1597            0 :                 final eventService = Provider.of<EventService>(context, listen: false);
    1598            0 :                 await eventService.deleteScore(widget.event.id, score.id);
    1599              :                 
    1600            0 :                 if (mounted) {
    1601            0 :                   setState(() {
    1602            0 :                     _scores.removeWhere((s) => s.id == score.id);
    1603            0 :                     _isLoading = false;
    1604              :                   });
    1605              :                   
    1606            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1607              :                     const SnackBar(content: Text('점수가 삭제되었습니다')),
    1608              :                   );
    1609              :                 }
    1610              :               } catch (e) {
    1611            0 :                 if (mounted) {
    1612            0 :                   setState(() {
    1613            0 :                     _isLoading = false;
    1614              :                   });
    1615              :                   
    1616            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1617            0 :                     SnackBar(content: Text('점수 삭제에 실패했습니다: $e')),
    1618              :                   );
    1619              :                 }
    1620              :               }
    1621              :             },
    1622            0 :             style: TextButton.styleFrom(foregroundColor: Colors.red),
    1623              :             child: const Text('삭제'),
    1624              :           ),
    1625              :         ],
    1626              :       ),
    1627              :     );
    1628              :   }
    1629              : 
    1630              :   // 점수 상세 정보 표시
    1631            0 :   void _showScoreDetails(Score score) {
    1632              :     // 참가자 이름 찾기
    1633            0 :     final participant = _participants.firstWhere(
    1634            0 :       (p) => p.memberId == score.memberId,
    1635            0 :       orElse: () => Participant(
    1636              :         id: '',
    1637              :         eventId: '',
    1638            0 :         memberId: score.memberId,
    1639              :         name: '알 수 없음',
    1640              :       ),
    1641              :     );
    1642              :     
    1643              :     // 점수 상세 정보 다이얼로그
    1644            0 :     showDialog(
    1645            0 :       context: context,
    1646            0 :       builder: (context) => AlertDialog(
    1647            0 :         title: Text('${participant.name} 점수'),
    1648            0 :         content: Column(
    1649              :           mainAxisSize: MainAxisSize.min,
    1650              :           crossAxisAlignment: CrossAxisAlignment.start,
    1651            0 :           children: [
    1652            0 :             _buildInfoRow(Icons.score, '총점: ${score.totalScore}'),
    1653            0 :             _buildInfoRow(
    1654              :               Icons.calendar_today,
    1655            0 :               '날짜: ${DateFormat('yyyy-MM-dd').format(score.date)}',
    1656              :             ),
    1657              :             const Divider(),
    1658              :             const Text('프레임별 점수:', style: TextStyle(fontWeight: FontWeight.bold)),
    1659              :             const SizedBox(height: 8),
    1660            0 :             Wrap(
    1661              :               spacing: 8,
    1662              :               runSpacing: 8,
    1663            0 :               children: score.frames.asMap().entries.map((entry) {
    1664            0 :                 return Container(
    1665              :                   width: 40,
    1666              :                   height: 40,
    1667            0 :                   decoration: BoxDecoration(
    1668            0 :                     border: Border.all(color: Colors.blue),
    1669            0 :                     borderRadius: BorderRadius.circular(4),
    1670              :                   ),
    1671            0 :                   child: Center(
    1672            0 :                     child: Text(
    1673            0 :                       entry.value.toString(),
    1674              :                       style: const TextStyle(
    1675              :                         fontSize: 16,
    1676              :                         fontWeight: FontWeight.bold,
    1677              :                       ),
    1678              :                     ),
    1679              :                   ),
    1680              :                 );
    1681            0 :               }).toList(),
    1682              :             ),
    1683            0 :             if (score.notes != null) ...[  
    1684              :               const Divider(),
    1685              :               const Text('메모:', style: TextStyle(fontWeight: FontWeight.bold)),
    1686            0 :               Text(score.notes ?? ''),
    1687              :             ],
    1688              :           ],
    1689              :         ),
    1690            0 :         actions: [
    1691            0 :           TextButton(
    1692            0 :             onPressed: () => Navigator.of(context).pop(),
    1693              :             child: const Text('닫기'),
    1694              :           ),
    1695              :         ],
    1696              :       ),
    1697              :     );
    1698              :   }
    1699              : 
    1700              :   
    1701              :   // 이벤트 알림 설정 기능
    1702            0 :   Future<void> _setEventReminders() async {
    1703            0 :     final notificationService = NotificationService();
    1704              :     
    1705              :     // 알림 권한 확인
    1706            0 :     final hasPermission = await notificationService.requestPermission();
    1707              :     
    1708              :     if (!hasPermission) {
    1709            0 :       if (mounted) {
    1710            0 :         ScaffoldMessenger.of(context).showSnackBar(
    1711              :           const SnackBar(content: Text('알림 권한이 없습니다. 설정에서 권한을 허용해주세요.')),
    1712              :         );
    1713              :       }
    1714              :       return;
    1715              :     }
    1716              :     
    1717              :     // 알림 설정 다이얼로그 표시
    1718            0 :     if (!mounted) return;
    1719              :     
    1720            0 :     showDialog(
    1721            0 :       context: context,
    1722            0 :       builder: (context) => AlertDialog(
    1723              :         title: const Text('이벤트 알림 설정'),
    1724            0 :         content: Column(
    1725              :           mainAxisSize: MainAxisSize.min,
    1726            0 :           children: [
    1727            0 :             ListTile(
    1728              :               leading: const Icon(Icons.notifications_active),
    1729              :               title: const Text('이벤트 시작 알림'),
    1730            0 :               subtitle: Text('${DateFormat('yyyy-MM-dd HH:mm').format(widget.event.startDate)} 1시간 전'),
    1731            0 :               onTap: () async {
    1732            0 :                 Navigator.of(context).pop();
    1733            0 :                 await notificationService.scheduleEventStartReminder(widget.event);
    1734              :                 
    1735            0 :                 if (mounted) {
    1736            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1737              :                     const SnackBar(content: Text('이벤트 시작 알림이 설정되었습니다')),
    1738              :                   );
    1739              :                 }
    1740              :               },
    1741              :             ),
    1742            0 :             if (widget.event.registrationDeadline != null) ListTile(
    1743              :               leading: const Icon(Icons.timer),
    1744              :               title: const Text('등록 마감 알림'),
    1745            0 :               subtitle: Text('${DateFormat('yyyy-MM-dd HH:mm').format(widget.event.registrationDeadline!)} 1일 전'),
    1746            0 :               onTap: () async {
    1747            0 :                 Navigator.of(context).pop();
    1748            0 :                 await notificationService.scheduleRegistrationDeadlineReminder(widget.event);
    1749              :                 
    1750            0 :                 if (mounted) {
    1751            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1752              :                     const SnackBar(content: Text('등록 마감 알림이 설정되었습니다')),
    1753              :                   );
    1754              :                 }
    1755              :               },
    1756              :             ),
    1757            0 :             ListTile(
    1758              :               leading: const Icon(Icons.notifications_off),
    1759              :               title: const Text('알림 취소'),
    1760              :               subtitle: const Text('이 이벤트에 대한 모든 알림 취소'),
    1761            0 :               onTap: () async {
    1762            0 :                 Navigator.of(context).pop();
    1763            0 :                 await notificationService.cancelEventNotifications(widget.event.id);
    1764              :                 
    1765            0 :                 if (mounted) {
    1766            0 :                   ScaffoldMessenger.of(context).showSnackBar(
    1767              :                     const SnackBar(content: Text('이벤트 알림이 취소되었습니다')),
    1768              :                   );
    1769              :                 }
    1770              :               },
    1771              :             ),
    1772              :           ],
    1773              :         ),
    1774            0 :         actions: [
    1775            0 :           TextButton(
    1776            0 :             onPressed: () => Navigator.of(context).pop(),
    1777              :             child: const Text('닫기'),
    1778              :           ),
    1779              :         ],
    1780              :       ),
    1781              :     );
    1782              :   }
    1783              : 
    1784              : }
        

Generated by: LCOV version 2.3.1-1