feat(ui): 장비 페이지 및 스탯 패널 개선
- equipment_page: 레이아웃 및 스타일 개선 - equipment_stats_panel: 스탯 표시 UI 업데이트
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||||
import 'package:askiineverdie/src/core/model/game_state.dart';
|
import 'package:askiineverdie/src/core/model/game_state.dart';
|
||||||
import 'package:askiineverdie/src/features/game/widgets/equipment_stats_panel.dart';
|
import 'package:askiineverdie/src/features/game/widgets/equipment_stats_panel.dart';
|
||||||
|
import 'package:askiineverdie/src/shared/retro_colors.dart';
|
||||||
|
|
||||||
/// 장비 페이지 (캐로셀)
|
/// 장비 페이지 (캐로셀)
|
||||||
///
|
///
|
||||||
@@ -29,17 +30,35 @@ class EquipmentPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSectionHeader(BuildContext context, String title) {
|
Widget _buildSectionHeader(BuildContext context, String title) {
|
||||||
|
final gold = RetroColors.goldOf(context);
|
||||||
|
final goldDark = RetroColors.goldDarkOf(context);
|
||||||
|
final panelBg = RetroColors.panelBgOf(context);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
color: Theme.of(context).colorScheme.primaryContainer,
|
decoration: BoxDecoration(
|
||||||
child: Text(
|
color: panelBg,
|
||||||
title,
|
border: Border(
|
||||||
style: TextStyle(
|
top: BorderSide(color: gold, width: 2),
|
||||||
fontWeight: FontWeight.bold,
|
left: BorderSide(color: gold, width: 2),
|
||||||
fontSize: 13,
|
bottom: BorderSide(color: goldDark, width: 2),
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
right: BorderSide(color: goldDark, width: 2),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.shield, size: 16, color: gold),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 13,
|
||||||
|
color: gold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:askiineverdie/src/core/model/equipment_item.dart';
|
|||||||
import 'package:askiineverdie/src/core/model/equipment_slot.dart';
|
import 'package:askiineverdie/src/core/model/equipment_slot.dart';
|
||||||
import 'package:askiineverdie/src/core/model/game_state.dart';
|
import 'package:askiineverdie/src/core/model/game_state.dart';
|
||||||
import 'package:askiineverdie/src/core/model/item_stats.dart';
|
import 'package:askiineverdie/src/core/model/item_stats.dart';
|
||||||
|
import 'package:askiineverdie/src/shared/retro_colors.dart';
|
||||||
|
|
||||||
/// 장비 스탯 표시 패널
|
/// 장비 스탯 표시 패널
|
||||||
///
|
///
|
||||||
@@ -130,7 +131,7 @@ class _EquipmentSlotTile extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 빈 슬롯 타일
|
/// 빈 슬롯 타일 (레트로 스타일)
|
||||||
class _EmptySlotTile extends StatelessWidget {
|
class _EmptySlotTile extends StatelessWidget {
|
||||||
const _EmptySlotTile({required this.slot});
|
const _EmptySlotTile({required this.slot});
|
||||||
|
|
||||||
@@ -138,6 +139,8 @@ class _EmptySlotTile extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final textMuted = RetroColors.textMutedOf(context);
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
@@ -146,7 +149,7 @@ class _EmptySlotTile extends StatelessWidget {
|
|||||||
'[${_getSlotName(slot)}] ${l10n.uiEmpty}',
|
'[${_getSlotName(slot)}] ${l10n.uiEmpty}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: Colors.grey.shade600,
|
color: textMuted,
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -154,7 +157,7 @@ class _EmptySlotTile extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 슬롯 아이콘
|
/// 슬롯 아이콘 (레트로 스타일)
|
||||||
class _SlotIcon extends StatelessWidget {
|
class _SlotIcon extends StatelessWidget {
|
||||||
const _SlotIcon({required this.slot, this.isEmpty = false});
|
const _SlotIcon({required this.slot, this.isEmpty = false});
|
||||||
|
|
||||||
@@ -177,15 +180,15 @@ class _SlotIcon extends StatelessWidget {
|
|||||||
EquipmentSlot.sollerets => Icons.do_not_step,
|
EquipmentSlot.sollerets => Icons.do_not_step,
|
||||||
};
|
};
|
||||||
|
|
||||||
return Icon(
|
final color = isEmpty
|
||||||
icon,
|
? RetroColors.textMutedOf(context)
|
||||||
size: 16,
|
: RetroColors.textSecondaryOf(context);
|
||||||
color: isEmpty ? Colors.grey.shade400 : Colors.grey.shade700,
|
|
||||||
);
|
return Icon(icon, size: 16, color: color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 점수 배지
|
/// 점수 배지 (레트로 스타일)
|
||||||
class _ScoreBadge extends StatelessWidget {
|
class _ScoreBadge extends StatelessWidget {
|
||||||
const _ScoreBadge({required this.score});
|
const _ScoreBadge({required this.score});
|
||||||
|
|
||||||
@@ -193,25 +196,29 @@ class _ScoreBadge extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final gold = RetroColors.goldOf(context);
|
||||||
|
final surface = RetroColors.surfaceOf(context);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blueGrey.shade100,
|
color: surface,
|
||||||
borderRadius: BorderRadius.circular(8),
|
border: Border.all(color: gold, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'$score',
|
'$score',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.blueGrey.shade700,
|
color: gold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 장비 점수 총합 헤더
|
/// 장비 점수 총합 헤더 (레트로 스타일)
|
||||||
class _TotalScoreHeader extends StatelessWidget {
|
class _TotalScoreHeader extends StatelessWidget {
|
||||||
const _TotalScoreHeader({
|
const _TotalScoreHeader({
|
||||||
required this.totalScore,
|
required this.totalScore,
|
||||||
@@ -225,26 +232,29 @@ class _TotalScoreHeader extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final gold = RetroColors.goldOf(context);
|
||||||
|
final goldDark = RetroColors.goldDarkOf(context);
|
||||||
|
final panelBg = RetroColors.panelBgOf(context);
|
||||||
|
final border = RetroColors.borderOf(context);
|
||||||
|
final textPrimary = RetroColors.textPrimaryOf(context);
|
||||||
|
final textSecondary = RetroColors.textSecondaryOf(context);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(bottom: 8),
|
margin: const EdgeInsets.only(bottom: 8),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
color: panelBg,
|
||||||
colors: [Colors.blueGrey.shade700, Colors.blueGrey.shade600],
|
border: Border(
|
||||||
|
top: BorderSide(color: gold, width: 2),
|
||||||
|
left: BorderSide(color: gold, width: 2),
|
||||||
|
bottom: BorderSide(color: goldDark, width: 2),
|
||||||
|
right: BorderSide(color: goldDark, width: 2),
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withValues(alpha: 0.2),
|
|
||||||
blurRadius: 4,
|
|
||||||
offset: const Offset(0, 2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
// 장비 아이콘
|
// 장비 아이콘
|
||||||
const Icon(Icons.shield, size: 20, color: Colors.white70),
|
Icon(Icons.shield, size: 20, color: gold),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
|
|
||||||
// 총합 점수
|
// 총합 점수
|
||||||
@@ -254,14 +264,14 @@ class _TotalScoreHeader extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
l10n.uiEquipmentScore,
|
l10n.uiEquipmentScore,
|
||||||
style: const TextStyle(fontSize: 10, color: Colors.white70),
|
style: TextStyle(fontSize: 10, color: textSecondary),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'$totalScore',
|
'$totalScore',
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white,
|
color: gold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -272,15 +282,15 @@ class _TotalScoreHeader extends StatelessWidget {
|
|||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withValues(alpha: 0.2),
|
color: border,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'$equippedCount / $totalSlots',
|
'$equippedCount / $totalSlots',
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.white,
|
color: textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -381,7 +391,7 @@ class _StatsGrid extends StatelessWidget {
|
|||||||
if (entries.isEmpty) {
|
if (entries.isEmpty) {
|
||||||
return Text(
|
return Text(
|
||||||
l10n.uiNoBonusStats,
|
l10n.uiNoBonusStats,
|
||||||
style: const TextStyle(fontSize: 10, color: Colors.grey),
|
style: TextStyle(fontSize: 10, color: RetroColors.textMutedOf(context)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +410,7 @@ class _StatEntry {
|
|||||||
final String value;
|
final String value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 스탯 칩
|
/// 스탯 칩 (레트로 스타일)
|
||||||
class _StatChip extends StatelessWidget {
|
class _StatChip extends StatelessWidget {
|
||||||
const _StatChip({required this.entry});
|
const _StatChip({required this.entry});
|
||||||
|
|
||||||
@@ -408,22 +418,32 @@ class _StatChip extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final surface = RetroColors.surfaceOf(context);
|
||||||
|
final border = RetroColors.borderOf(context);
|
||||||
|
final textMuted = RetroColors.textMutedOf(context);
|
||||||
|
final textPrimary = RetroColors.textPrimaryOf(context);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey.shade200,
|
color: surface,
|
||||||
borderRadius: BorderRadius.circular(4),
|
border: Border.all(color: border, width: 1),
|
||||||
|
borderRadius: BorderRadius.circular(2),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${entry.label}: ',
|
'${entry.label}: ',
|
||||||
style: TextStyle(fontSize: 9, color: Colors.grey.shade600),
|
style: TextStyle(fontSize: 9, color: textMuted),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
entry.value,
|
entry.value,
|
||||||
style: const TextStyle(fontSize: 9, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: textPrimary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -431,7 +451,7 @@ class _StatChip extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 아이템 메타 정보 행
|
/// 아이템 메타 정보 행 (레트로 스타일)
|
||||||
class _ItemMetaRow extends StatelessWidget {
|
class _ItemMetaRow extends StatelessWidget {
|
||||||
const _ItemMetaRow({required this.item});
|
const _ItemMetaRow({required this.item});
|
||||||
|
|
||||||
@@ -440,12 +460,13 @@ class _ItemMetaRow extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final rarityName = _getTranslatedRarity(item.rarity);
|
final rarityName = _getTranslatedRarity(item.rarity);
|
||||||
|
final textMuted = RetroColors.textMutedOf(context);
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
l10n.uiLevel(item.level),
|
l10n.uiLevel(item.level),
|
||||||
style: const TextStyle(fontSize: 9, color: Colors.grey),
|
style: TextStyle(fontSize: 9, color: textMuted),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
@@ -459,7 +480,7 @@ class _ItemMetaRow extends StatelessWidget {
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
l10n.uiWeight(item.weight),
|
l10n.uiWeight(item.weight),
|
||||||
style: const TextStyle(fontSize: 9, color: Colors.grey),
|
style: TextStyle(fontSize: 9, color: textMuted),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user