import 'package:flutter/material.dart'; import 'package:asciineverdie/data/game_text_l10n.dart' as game_l10n; import 'package:asciineverdie/l10n/app_localizations.dart'; import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart'; import 'package:asciineverdie/src/core/model/race_traits.dart'; import 'package:asciineverdie/src/shared/retro_colors.dart'; import 'package:asciineverdie/src/shared/widgets/retro_widgets.dart'; /// 종족 선택 섹션 class RaceSelectionSection extends StatelessWidget { const RaceSelectionSection({ super.key, required this.races, required this.selectedIndex, required this.scrollController, required this.onSelected, }); final List races; final int selectedIndex; final ScrollController scrollController; final ValueChanged onSelected; @override Widget build(BuildContext context) { return RetroPanel( title: L10n.of(context).raceTitle, child: SizedBox( height: 300, child: ListView.builder( controller: scrollController, itemCount: races.length, itemBuilder: (context, index) { final isSelected = index == selectedIndex; final race = races[index]; return GestureDetector( onTap: () => onSelected(index), child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), decoration: BoxDecoration( color: isSelected ? RetroColors.panelBgLight : null, border: isSelected ? Border.all(color: RetroColors.gold, width: 1) : null, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( isSelected ? Icons.arrow_right : Icons.remove, size: 12, color: isSelected ? RetroColors.gold : RetroColors.textDisabled, ), const SizedBox(width: 4), Expanded( child: Text( GameDataL10n.getRaceName(context, race.name), style: TextStyle( fontFamily: 'PressStart2P', fontSize: 14, color: isSelected ? RetroColors.gold : RetroColors.textLight, ), ), ), ], ), if (isSelected) _RaceInfo(race: race), ], ), ), ); }, ), ), ); } } /// 종족 정보 표시 위젯 class _RaceInfo extends StatelessWidget { const _RaceInfo({required this.race}); final RaceTraits race; String _statName(StatType type) { return switch (type) { StatType.str => game_l10n.statStr, StatType.con => game_l10n.statCon, StatType.dex => game_l10n.statDex, StatType.intelligence => game_l10n.statInt, StatType.wis => game_l10n.statWis, StatType.cha => game_l10n.statCha, }; } String _translatePassive(PassiveAbility passive) { final percent = (passive.value * 100).round(); return switch (passive.type) { PassiveType.hpBonus => game_l10n.passiveHpBonus(percent), PassiveType.mpBonus => game_l10n.passiveMpBonus(percent), PassiveType.defenseBonus => game_l10n.passiveDefenseBonus(percent), PassiveType.magicDamageBonus => game_l10n.passiveMagicBonus(percent), PassiveType.criticalBonus => game_l10n.passiveCritBonus(percent), PassiveType.expBonus => passive.description, }; } @override Widget build(BuildContext context) { final statMods = []; for (final entry in race.statModifiers.entries) { final sign = entry.value > 0 ? '+' : ''; statMods.add('${_statName(entry.key)} $sign${entry.value}'); } final passiveDesc = race.passives.isNotEmpty ? race.passives.map((p) => _translatePassive(p)).join(', ') : ''; return Padding( padding: const EdgeInsets.only(left: 16, top: 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (statMods.isNotEmpty) Text( statMods.join(', '), style: const TextStyle( fontSize: 15, color: RetroColors.textLight, ), ), if (passiveDesc.isNotEmpty) Text( passiveDesc, style: const TextStyle(fontSize: 15, color: RetroColors.expGreen), ), ], ), ); } }