Files
asciinevrdie/lib/src/features/game/widgets/desktop_quest_panel.dart
JiWoong Sul 864a866039 refactor(ui): 위젯 분리 및 화면 개선
- game_play_screen에서 desktop 패널 위젯 분리
- death_overlay에서 death_buttons, death_combat_log 분리
- mobile_carousel_layout에서 mobile_options_menu 분리
- 아레나 위젯 개선 (arena_hp_bar, result_panel 등)
- settings_screen에서 retro_settings_widgets 분리
- 기타 위젯 리팩토링 및 import 경로 업데이트
2026-02-23 15:49:38 +09:00

213 lines
6.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:asciineverdie/l10n/app_localizations.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/util/pq_logic.dart' as pq_logic;
import 'package:asciineverdie/src/core/util/roman.dart' show intToRoman;
import 'package:asciineverdie/src/features/game/widgets/desktop_panel_widgets.dart';
import 'package:asciineverdie/src/shared/retro_colors.dart';
/// 데스크톱 우측 패널: Plot/Quest
///
/// Plot Development, Quests 목록 및 프로그레스 바 표시
class DesktopQuestPanel extends StatelessWidget {
const DesktopQuestPanel({super.key, required this.state});
final GameState state;
@override
Widget build(BuildContext context) {
final l10n = L10n.of(context);
return Card(
margin: const EdgeInsets.all(4),
color: RetroColors.panelBg,
shape: RoundedRectangleBorder(
side: const BorderSide(
color: RetroColors.panelBorderOuter,
width: 2,
),
borderRadius: BorderRadius.circular(0),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
DesktopPanelHeader(title: l10n.plotDevelopment),
Expanded(child: _PlotList(state: state)),
DesktopSegmentProgressBar(
position: state.progress.plot.position,
max: state.progress.plot.max,
color: Colors.purple,
tooltip: state.progress.plot.max > 0
? '${pq_logic.roughTime(state.progress.plot.max - state.progress.plot.position)} remaining'
: null,
),
DesktopPanelHeader(title: l10n.quests),
Expanded(child: _QuestList(state: state)),
DesktopSegmentProgressBar(
position: state.progress.quest.position,
max: state.progress.quest.max,
color: Colors.green,
tooltip: state.progress.quest.max > 0
? l10n.percentComplete(
100 *
state.progress.quest.position ~/
state.progress.quest.max,
)
: null,
),
],
),
);
}
}
/// Plot 목록 위젯
class _PlotList extends StatelessWidget {
const _PlotList({required this.state});
final GameState state;
@override
Widget build(BuildContext context) {
final l10n = L10n.of(context);
final plotCount = state.progress.plotStageCount;
if (plotCount == 0) {
return Center(
child: Text(
l10n.prologue.toUpperCase(),
style: const TextStyle(
fontFamily: 'PressStart2P',
fontSize: 14,
color: RetroColors.textDisabled,
),
),
);
}
return ListView.builder(
itemCount: plotCount,
padding: const EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, index) {
final isCompleted = index < plotCount - 1;
final isCurrent = index == plotCount - 1;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 1),
child: Row(
children: [
Icon(
isCompleted
? Icons.check_box
: (isCurrent
? Icons.arrow_right
: Icons.check_box_outline_blank),
size: 12,
color: isCompleted
? RetroColors.expGreen
: (isCurrent
? RetroColors.gold
: RetroColors.textDisabled),
),
const SizedBox(width: 4),
Expanded(
child: Text(
index == 0
? l10n.prologue
: l10n.actNumber(intToRoman(index)),
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 13,
color: isCompleted
? RetroColors.textDisabled
: (isCurrent
? RetroColors.gold
: RetroColors.textLight),
decoration: isCompleted
? TextDecoration.lineThrough
: TextDecoration.none,
),
),
),
],
),
);
},
);
}
}
/// Quest 목록 위젯
class _QuestList extends StatelessWidget {
const _QuestList({required this.state});
final GameState state;
@override
Widget build(BuildContext context) {
final l10n = L10n.of(context);
final questHistory = state.progress.questHistory;
if (questHistory.isEmpty) {
return Center(
child: Text(
l10n.noActiveQuests.toUpperCase(),
style: const TextStyle(
fontFamily: 'PressStart2P',
fontSize: 14,
color: RetroColors.textDisabled,
),
),
);
}
return ListView.builder(
itemCount: questHistory.length,
padding: const EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, index) {
final quest = questHistory[index];
final isCurrentQuest =
index == questHistory.length - 1 && !quest.isComplete;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 1),
child: Row(
children: [
Icon(
isCurrentQuest
? Icons.arrow_right
: (quest.isComplete
? Icons.check_box
: Icons.check_box_outline_blank),
size: 12,
color: isCurrentQuest
? RetroColors.gold
: (quest.isComplete
? RetroColors.expGreen
: RetroColors.textDisabled),
),
const SizedBox(width: 4),
Expanded(
child: Text(
quest.caption,
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 13,
color: isCurrentQuest
? RetroColors.gold
: (quest.isComplete
? RetroColors.textDisabled
: RetroColors.textLight),
decoration: quest.isComplete
? TextDecoration.lineThrough
: TextDecoration.none,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
);
},
);
}
}