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