이벤트 가져오기 위젯 테스트 추가 및 테스트 훅 도입
This commit is contained in:
@@ -40,7 +40,8 @@ class _ClubStatisticsScreenState extends State<ClubStatisticsScreen> {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
// await 이전에 messenger 캡처하여 안전하게 사용
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
try {
|
||||
final authService = Provider.of<AuthService>(context, listen: false);
|
||||
final clubService = Provider.of<ClubService>(context, listen: false);
|
||||
@@ -73,9 +74,9 @@ class _ClubStatisticsScreenState extends State<ClubStatisticsScreen> {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $e')));
|
||||
messenger.showSnackBar(
|
||||
SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
||||
@@ -10,6 +10,7 @@ import '../../services/score_service.dart';
|
||||
import '../../models/member_model.dart';
|
||||
import '../../models/score_model.dart';
|
||||
import 'score_entry_screen.dart';
|
||||
import '../../widgets/dialog_actions.dart';
|
||||
|
||||
class MemberStatisticsScreen extends StatefulWidget {
|
||||
final String memberId;
|
||||
@@ -56,12 +57,15 @@ class _MemberStatisticsScreenState extends State<MemberStatisticsScreen>
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
// await 이전에 messenger 캡처
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
|
||||
try {
|
||||
final authService = Provider.of<AuthService>(context, listen: false);
|
||||
final clubService = Provider.of<ClubService>(context, listen: false);
|
||||
final memberService = Provider.of<MemberService>(context, listen: false);
|
||||
final scoreService = Provider.of<ScoreService>(context, listen: false);
|
||||
|
||||
final clubService = Provider.of<ClubService>(context, listen: false);
|
||||
|
||||
if (clubService.currentClub != null) {
|
||||
// 회원 정보 로드
|
||||
_member = await memberService.fetchMemberById(widget.memberId);
|
||||
@@ -80,13 +84,15 @@ class _MemberStatisticsScreenState extends State<MemberStatisticsScreen>
|
||||
]);
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $e')));
|
||||
messenger.showSnackBar(
|
||||
SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,7 +614,7 @@ class _MemberStatisticsScreenState extends State<MemberStatisticsScreen>
|
||||
dotData: const FlDotData(show: true),
|
||||
belowBarData: BarAreaData(
|
||||
show: true,
|
||||
color: Colors.blue.withOpacity(0.2),
|
||||
color: Colors.blue.withValues(alpha: 0.2),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -619,43 +625,28 @@ class _MemberStatisticsScreenState extends State<MemberStatisticsScreen>
|
||||
void _showDeleteConfirmationDialog(Score score) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
builder: (dialogContext) => AlertDialog(
|
||||
title: const Text('점수 삭제'),
|
||||
content: const Text('이 점수 기록을 정말 삭제하시겠습니까?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('취소'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
try {
|
||||
final scoreService = Provider.of<ScoreService>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
await scoreService.deleteScore(score.id);
|
||||
|
||||
// 데이터 새로고침
|
||||
_loadMemberData();
|
||||
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('점수가 삭제되었습니다')));
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('점수 삭제에 실패했습니다: $e')));
|
||||
}
|
||||
},
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
child: const Text('삭제'),
|
||||
),
|
||||
],
|
||||
actions: DialogActions.confirm(
|
||||
onCancel: () => Navigator.of(dialogContext).pop(),
|
||||
onConfirm: () async {
|
||||
// await 전에 필요한 객체 캡처
|
||||
final navigator = Navigator.of(dialogContext);
|
||||
final messenger = ScaffoldMessenger.of(dialogContext);
|
||||
final scoreService = Provider.of<ScoreService>(dialogContext, listen: false);
|
||||
navigator.pop();
|
||||
try {
|
||||
await scoreService.deleteScore(score.id);
|
||||
_loadMemberData();
|
||||
messenger.showSnackBar(const SnackBar(content: Text('점수가 삭제되었습니다')));
|
||||
} catch (e) {
|
||||
messenger.showSnackBar(SnackBar(content: Text('점수 삭제에 실패했습니다: $e')));
|
||||
}
|
||||
},
|
||||
destructive: true,
|
||||
confirmText: '삭제',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,21 +65,16 @@ class _ScoreEntryScreenState extends State<ScoreEntryScreen> {
|
||||
|
||||
// 점수 저장
|
||||
Future<void> _saveScore() async {
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectedMemberId == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('회원을 선택해주세요')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
|
||||
// await 전에 필요한 파생 객체 캡처 (catch에서도 사용 가능하도록 try 밖)
|
||||
final navigator = Navigator.of(context);
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
|
||||
try {
|
||||
final scoreService = Provider.of<ScoreService>(context, listen: false);
|
||||
final clubService = Provider.of<ClubService>(context, listen: false);
|
||||
@@ -106,22 +101,23 @@ class _ScoreEntryScreenState extends State<ScoreEntryScreen> {
|
||||
|
||||
// 점수 저장
|
||||
await scoreService.addScore(scoreData);
|
||||
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('점수가 저장되었습니다')),
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
// 성공 알림 및 화면 닫기
|
||||
messenger.showSnackBar(
|
||||
const SnackBar(content: Text('점수가 저장되었습니다')),
|
||||
);
|
||||
navigator.pop();
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
// 에러 알림 (사전 캡처한 messenger 사용)
|
||||
messenger.showSnackBar(
|
||||
SnackBar(content: Text('점수 저장에 실패했습니다: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,15 +193,21 @@ class _ScoreEntryScreenState extends State<ScoreEntryScreen> {
|
||||
final members = memberService.members;
|
||||
|
||||
return DropdownButtonFormField<String>(
|
||||
key: const Key('score_entry_member_dropdown'),
|
||||
decoration: const InputDecoration(
|
||||
labelText: '회원 선택',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
value: _selectedMemberId,
|
||||
isExpanded: true,
|
||||
items: members.map((member) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: member.id,
|
||||
child: Text(member.name),
|
||||
child: Text(
|
||||
member.name,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
@@ -230,11 +232,13 @@ class _ScoreEntryScreenState extends State<ScoreEntryScreen> {
|
||||
final events = eventService.events;
|
||||
|
||||
return DropdownButtonFormField<String>(
|
||||
key: const Key('score_entry_event_dropdown'),
|
||||
decoration: const InputDecoration(
|
||||
labelText: '이벤트 선택 (선택사항)',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
value: _selectedEventId,
|
||||
isExpanded: true,
|
||||
items: [
|
||||
const DropdownMenuItem<String>(
|
||||
value: null,
|
||||
@@ -243,7 +247,11 @@ class _ScoreEntryScreenState extends State<ScoreEntryScreen> {
|
||||
...events.map((event) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: event.id,
|
||||
child: Text(event.title),
|
||||
child: Text(
|
||||
event.title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user