refactor(ui): HallOfFameScreen 위젯 분해
- HeroDetailDialog: 상세 정보 다이얼로그 분리 (690줄) - HallOfFameEntryCard: 엔트리 카드 분리 (263줄) - GameClearDialog: 게임 클리어 다이얼로그 분리 (255줄) - 메인 화면 264줄로 경량화
This commit is contained in:
255
lib/src/features/hall_of_fame/game_clear_dialog.dart
Normal file
255
lib/src/features/hall_of_fame/game_clear_dialog.dart
Normal file
@@ -0,0 +1,255 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:asciineverdie/data/game_text_l10n.dart' as l10n;
|
||||
import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart';
|
||||
import 'package:asciineverdie/src/core/model/hall_of_fame.dart';
|
||||
import 'package:asciineverdie/src/shared/retro_colors.dart';
|
||||
|
||||
/// 게임 클리어 축하 다이얼로그 표시 함수
|
||||
Future<void> showGameClearDialog(
|
||||
BuildContext context, {
|
||||
required HallOfFameEntry entry,
|
||||
required VoidCallback onNewGame,
|
||||
required VoidCallback onViewHallOfFame,
|
||||
}) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => GameClearDialog(
|
||||
entry: entry,
|
||||
onNewGame: onNewGame,
|
||||
onViewHallOfFame: onViewHallOfFame,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 게임 클리어 다이얼로그 위젯
|
||||
class GameClearDialog extends StatelessWidget {
|
||||
const GameClearDialog({
|
||||
super.key,
|
||||
required this.entry,
|
||||
required this.onNewGame,
|
||||
required this.onViewHallOfFame,
|
||||
});
|
||||
|
||||
final HallOfFameEntry entry;
|
||||
final VoidCallback onNewGame;
|
||||
final VoidCallback onViewHallOfFame;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final goldColor = RetroColors.goldOf(context);
|
||||
final panelBg = RetroColors.panelBgOf(context);
|
||||
final borderColor = RetroColors.borderOf(context);
|
||||
|
||||
return Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 400),
|
||||
decoration: BoxDecoration(
|
||||
color: panelBg,
|
||||
border: Border(
|
||||
top: BorderSide(color: goldColor, width: 3),
|
||||
left: BorderSide(color: goldColor, width: 3),
|
||||
bottom: BorderSide(color: borderColor, width: 3),
|
||||
right: BorderSide(color: borderColor, width: 3),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: goldColor.withValues(alpha: 0.4),
|
||||
blurRadius: 24,
|
||||
spreadRadius: 4,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 헤더
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: goldColor.withValues(alpha: 0.2),
|
||||
border: Border(bottom: BorderSide(color: goldColor, width: 2)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.emoji_events, color: goldColor, size: 20),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
l10n.hofVictory.toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 12,
|
||||
color: goldColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Icon(Icons.emoji_events, color: goldColor, size: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 컨텐츠
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
l10n.hofDefeatedGlitchGod,
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 7,
|
||||
color: RetroColors.textPrimaryOf(context),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(height: 2, color: borderColor),
|
||||
const SizedBox(height: 16),
|
||||
// 캐릭터 정보
|
||||
Text(
|
||||
entry.characterName,
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 10,
|
||||
color: goldColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'${GameDataL10n.getRaceName(context, entry.race)} '
|
||||
'${GameDataL10n.getKlassName(context, entry.klass)}',
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 6,
|
||||
color: RetroColors.textSecondaryOf(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
// 통계
|
||||
Wrap(
|
||||
spacing: 12,
|
||||
runSpacing: 8,
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
_buildStat(context, l10n.hofLevel, '${entry.level}'),
|
||||
_buildStat(
|
||||
context,
|
||||
l10n.hofTime,
|
||||
entry.formattedPlayTime,
|
||||
),
|
||||
_buildStat(
|
||||
context,
|
||||
l10n.hofDeaths,
|
||||
'${entry.totalDeaths}',
|
||||
),
|
||||
_buildStat(
|
||||
context,
|
||||
l10n.hofQuests,
|
||||
'${entry.questsCompleted}',
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
l10n.hofLegendEnshrined,
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 6,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: goldColor,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 버튼
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
onViewHallOfFame();
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: BorderSide(color: borderColor, width: 2),
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
),
|
||||
child: Text(
|
||||
l10n.hofViewHallOfFame.toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 6,
|
||||
color: RetroColors.textSecondaryOf(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
onNewGame();
|
||||
},
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: goldColor,
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
),
|
||||
child: Text(
|
||||
l10n.hofNewGame.toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 6,
|
||||
color: RetroColors.backgroundOf(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStat(BuildContext context, String label, String value) {
|
||||
final goldColor = RetroColors.goldOf(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: goldColor.withValues(alpha: 0.1),
|
||||
border: Border.all(color: goldColor.withValues(alpha: 0.3), width: 1),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 8,
|
||||
color: goldColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontFamily: 'PressStart2P',
|
||||
fontSize: 5,
|
||||
color: RetroColors.textMutedOf(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user