feat(ui): 장비 페이지 및 스탯 패널 개선

- equipment_page: 레이아웃 및 스타일 개선
- equipment_stats_panel: 스탯 표시 UI 업데이트
This commit is contained in:
JiWoong Sul
2025-12-31 15:09:15 +09:00
parent 72676485d3
commit 83796f805e
2 changed files with 88 additions and 48 deletions

View File

@@ -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,
),
),
],
),
); );
} }
} }

View File

@@ -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),
), ),
], ],
); );