Files
asciinevrdie/lib/src/features/game/pages/inventory_page.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

162 lines
4.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:asciineverdie/data/game_text_l10n.dart' as l10n;
import 'package:asciineverdie/l10n/app_localizations.dart';
import 'package:asciineverdie/src/shared/l10n/game_data_l10n.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/potion.dart';
import 'package:asciineverdie/src/features/game/widgets/potion_inventory_panel.dart';
/// 인벤토리 페이지 (캐로셀)
///
/// 골드, 아이템 목록, 물약 인벤토리, 무게 표시.
class InventoryPage extends StatelessWidget {
const InventoryPage({
super.key,
required this.inventory,
required this.potionInventory,
required this.encumbrance,
});
final Inventory inventory;
final PotionInventory potionInventory;
final ProgressBarState encumbrance;
@override
Widget build(BuildContext context) {
final localizations = L10n.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 인벤토리 (아이템)
_buildSectionHeader(context, localizations.inventory),
Expanded(flex: 2, child: _buildInventoryList(context)),
// 물약
_buildSectionHeader(context, l10n.uiPotions),
Expanded(
flex: 2,
child: PotionInventoryPanel(inventory: potionInventory),
),
// 무게 (Encumbrance)
_buildSectionHeader(context, localizations.encumbrance),
_buildProgressBar(context),
],
);
}
Widget _buildSectionHeader(BuildContext context, String title) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
color: Theme.of(context).colorScheme.primaryContainer,
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
),
);
}
Widget _buildInventoryList(BuildContext context) {
final localizations = L10n.of(context);
return ListView.builder(
itemCount: inventory.items.length + 1, // +1 for gold
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
itemBuilder: (context, index) {
if (index == 0) {
// 골드 표시
return Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Row(
children: [
const Icon(
Icons.monetization_on,
size: 16,
color: Colors.amber,
),
const SizedBox(width: 8),
Expanded(
child: Text(
localizations.gold,
style: const TextStyle(fontSize: 18),
),
),
Text(
'${inventory.gold}',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.amber,
),
),
],
),
);
}
final item = inventory.items[index - 1];
final translatedName = GameDataL10n.translateItemString(
context,
item.name,
);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Row(
children: [
const Icon(Icons.inventory_2, size: 16, color: Colors.grey),
const SizedBox(width: 8),
Expanded(
child: Text(
translatedName,
style: const TextStyle(fontSize: 18),
overflow: TextOverflow.ellipsis,
),
),
Text(
'${item.count}',
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
),
),
],
),
);
},
);
}
Widget _buildProgressBar(BuildContext context) {
final progress = encumbrance.max > 0
? (encumbrance.position / encumbrance.max).clamp(0.0, 1.0)
: 0.0;
final percentage = (progress * 100).toInt();
return Padding(
padding: const EdgeInsets.all(12),
child: Column(
children: [
LinearProgressIndicator(
value: progress,
backgroundColor: Colors.orange.withValues(alpha: 0.2),
valueColor: const AlwaysStoppedAnimation<Color>(Colors.orange),
minHeight: 12,
),
const SizedBox(height: 4),
Text(
'$percentage%',
style: TextStyle(fontSize: 15, color: Colors.grey.shade600),
),
],
),
);
}
}