Files
asciinevrdie/lib/src/features/game/widgets/potion_inventory_panel.dart
JiWoong Sul 1da6fa7a2b feat(l10n): 게임 텍스트 다국어 지원 확장
- game_text_l10n.dart: 스탯/UI 텍스트 추가 (+61 라인)
- 한국어/일본어 번역 업데이트
- game_data_l10n.dart: 텍스트 접근자 추가
- equipment_stats_panel: l10n 적용 및 레이아웃 개선
- active_buff_panel, potion_inventory_panel: 코드 정리
- new_character_screen: 코드 정리
- progress_service: 마이너 개선
2025-12-23 15:51:56 +09:00

233 lines
5.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:askiineverdie/data/game_text_l10n.dart' as l10n;
import 'package:askiineverdie/data/potion_data.dart';
import 'package:askiineverdie/src/core/model/potion.dart';
/// 물약 인벤토리 패널
///
/// 보유 중인 물약 목록과 수량을 표시.
/// HP 물약은 빨간색, MP 물약은 파란색으로 구분.
class PotionInventoryPanel extends StatelessWidget {
const PotionInventoryPanel({
super.key,
required this.inventory,
this.usedInBattle = const {},
});
final PotionInventory inventory;
final Set<PotionType> usedInBattle;
@override
Widget build(BuildContext context) {
final potionEntries = _buildPotionEntries();
if (potionEntries.isEmpty) {
return Center(
child: Text(
l10n.uiNoPotions,
style: const TextStyle(
fontSize: 11,
color: Colors.grey,
fontStyle: FontStyle.italic,
),
),
);
}
return ListView.builder(
itemCount: potionEntries.length,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
itemBuilder: (context, index) {
final entry = potionEntries[index];
return _PotionRow(
potion: entry.potion,
quantity: entry.quantity,
isUsedThisBattle: usedInBattle.contains(entry.potion.type),
);
},
);
}
/// 물약 엔트리 목록 생성
///
/// HP 물약 먼저, MP 물약 나중에 정렬
List<_PotionEntry> _buildPotionEntries() {
final entries = <_PotionEntry>[];
for (final potionId in inventory.potions.keys) {
final quantity = inventory.potions[potionId] ?? 0;
if (quantity <= 0) continue;
final potion = PotionData.getById(potionId);
if (potion == null) continue;
entries.add(_PotionEntry(potion: potion, quantity: quantity));
}
// HP 물약 우선, 같은 타입 내에서는 티어순
entries.sort((a, b) {
final typeCompare = a.potion.type.index.compareTo(b.potion.type.index);
if (typeCompare != 0) return typeCompare;
return a.potion.tier.compareTo(b.potion.tier);
});
return entries;
}
}
/// 물약 엔트리
class _PotionEntry {
const _PotionEntry({required this.potion, required this.quantity});
final Potion potion;
final int quantity;
}
/// 물약 행 위젯
class _PotionRow extends StatelessWidget {
const _PotionRow({
required this.potion,
required this.quantity,
this.isUsedThisBattle = false,
});
final Potion potion;
final int quantity;
final bool isUsedThisBattle;
@override
Widget build(BuildContext context) {
final color = _getPotionColor();
final opacity = isUsedThisBattle ? 0.5 : 1.0;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Opacity(
opacity: opacity,
child: Row(
children: [
// 물약 아이콘
_PotionIcon(type: potion.type, tier: potion.tier),
const SizedBox(width: 4),
// 물약 이름 (번역 적용)
Expanded(
child: Text(
l10n.translateSpell(potion.name),
style: TextStyle(
fontSize: 11,
color: color,
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
),
),
// 회복량 표시
_HealBadge(potion: potion),
const SizedBox(width: 4),
// 수량
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: color.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'x$quantity',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: color,
),
),
),
// 전투 중 사용 불가 표시
if (isUsedThisBattle) ...[
const SizedBox(width: 4),
const Icon(Icons.block, size: 12, color: Colors.grey),
],
],
),
),
);
}
Color _getPotionColor() {
return switch (potion.type) {
PotionType.hp => Colors.red.shade700,
PotionType.mp => Colors.blue.shade700,
};
}
}
/// 물약 아이콘
class _PotionIcon extends StatelessWidget {
const _PotionIcon({required this.type, required this.tier});
final PotionType type;
final int tier;
@override
Widget build(BuildContext context) {
final color = type == PotionType.hp
? Colors.red.shade400
: Colors.blue.shade400;
// 티어에 따른 아이콘 크기 조절
final size = 12.0 + tier * 1.0;
return Container(
width: 18,
height: 18,
alignment: Alignment.center,
child: Icon(
type == PotionType.hp ? Icons.favorite : Icons.bolt,
size: size.clamp(12, 18),
color: color,
),
);
}
}
/// 회복량 배지
class _HealBadge extends StatelessWidget {
const _HealBadge({required this.potion});
final Potion potion;
@override
Widget build(BuildContext context) {
final healText = _buildHealText();
return Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(4),
),
child: Text(
healText,
style: TextStyle(fontSize: 9, color: Colors.grey.shade700),
),
);
}
String _buildHealText() {
final parts = <String>[];
if (potion.healAmount > 0) {
parts.add('+${potion.healAmount}');
}
if (potion.healPercent > 0) {
final percent = (potion.healPercent * 100).round();
parts.add('+$percent%');
}
return parts.join(' ');
}
}