import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lucide_icons/lucide_icons.dart'; import '../../providers/theme_provider.dart'; import '../../providers/ui_experiment_provider.dart'; import '../contextual_help_icon.dart'; import '../../theme/app_colors.dart'; class BadgeCase extends ConsumerWidget { const BadgeCase({super.key}); static const List> _badges = [ // Activity Badges (登録数) {'id': 'first_step', 'name': '初めての一歩', 'emoji': '🍶', 'icon': LucideIcons.footprints, 'desc': '最初の1本を登録'}, {'id': 'collector_10', 'name': '愛好家', 'emoji': '🎉', 'icon': LucideIcons.star, 'desc': '10本以上登録'}, {'id': 'collector_50', 'name': 'コレクター', 'emoji': '📚', 'icon': LucideIcons.award, 'desc': '50本以上登録'}, {'id': 'collector_100', 'name': 'レジェンド', 'emoji': '👑', 'icon': LucideIcons.crown, 'desc': '100本以上登録'}, // Regional Badges (地域制覇) {'id': 'regional_tohoku', 'name': '東北制覇', 'emoji': '👹', 'icon': LucideIcons.snowflake, 'desc': '東北6県の日本酒を登録'}, {'id': 'regional_kanto', 'name': '関東制覇', 'emoji': '🗻', 'icon': LucideIcons.building2, 'desc': '関東7都県の日本酒を登録'}, {'id': 'regional_kansai', 'name': '関西制覇', 'emoji': '🏯', 'icon': LucideIcons.landmark, 'desc': '関西6府県の日本酒を登録'}, // Flavor Badges (味覚) {'id': 'flavor_dry', 'name': '辛口党', 'emoji': '🌶️', 'icon': LucideIcons.flame, 'desc': '辛口(+5以上)を10本登録'}, {'id': 'flavor_sweet', 'name': '甘口党', 'emoji': '🍯', 'icon': LucideIcons.candy, 'desc': '甘口(-3以下)を10本登録'}, {'id': 'flavor_aromatic', 'name': '香りの貴族', 'emoji': '🌸', 'icon': LucideIcons.flower, 'desc': '華やか(80以上)を10本登録'}, ]; @override Widget build(BuildContext context, WidgetRef ref) { final userProfile = ref.watch(userProfileProvider); final unlocked = userProfile.unlockedBadges.toSet(); final useIcons = ref.watch(uiExperimentProvider).useBadgeIcons; final appColors = Theme.of(context).extension()!; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(16), border: Border.all( color: Theme.of(context).dividerColor.withValues(alpha: 0.1), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Row( children: [ Text( 'バッジケース', style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(width: 4), ContextualHelpIcon( title: 'バッジについて', customContent: _buildHelpContent(context, useIcons), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: appColors.brandPrimary.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), border: Border.all( color: appColors.brandPrimary.withValues(alpha: 0.4), ), ), child: Text( '${unlocked.length} / ${_badges.length}', style: TextStyle( fontSize: 13, fontWeight: FontWeight.bold, color: appColors.brandPrimary, ), ), ), ], ), const SizedBox(height: 16), Wrap( spacing: 12, runSpacing: 12, children: _badges.map((badge) { final isUnlocked = unlocked.contains(badge['id']); return Tooltip( message: '${badge['name']}\n${badge['desc']}', triggerMode: TooltipTriggerMode.tap, child: AnimatedContainer( duration: const Duration(milliseconds: 300), width: 64, height: 80, child: Column( children: [ Container( width: 50, height: 50, alignment: Alignment.center, decoration: BoxDecoration( color: isUnlocked ? appColors.brandPrimary.withValues(alpha: 0.2) : appColors.surfaceSubtle, shape: BoxShape.circle, border: Border.all( color: isUnlocked ? appColors.brandPrimary : appColors.divider, width: 2.5, ), boxShadow: isUnlocked ? [ BoxShadow( color: appColors.brandPrimary.withValues(alpha: 0.3), blurRadius: 10, spreadRadius: 1, ) ] : [], ), child: isUnlocked ? (useIcons ? Icon(badge['icon'], color: appColors.brandPrimary, size: 24) : Text(badge['emoji'], style: const TextStyle(fontSize: 24))) : Icon(LucideIcons.lock, color: appColors.iconSubtle, size: 20), ), const SizedBox(height: 4), Text( badge['name'], style: TextStyle( fontSize: 10, fontWeight: isUnlocked ? FontWeight.bold : FontWeight.normal, color: isUnlocked ? appColors.textPrimary : appColors.textTertiary, ), overflow: TextOverflow.ellipsis, ), ], ), ), ); }).toList(), ), ], ), ); } Widget _buildHelpContent(BuildContext context, bool useIcons) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('バッジは特定の条件を達成すると獲得できます。\n\n【活動バッジ】'), ..._buildBadgeHelpRows(context, useIcons, ['first_step', 'collector_10', 'collector_50', 'collector_100']), const SizedBox(height: 12), const Text('【地域バッジ】'), ..._buildBadgeHelpRows(context, useIcons, ['regional_tohoku', 'regional_kanto', 'regional_kansai']), const SizedBox(height: 12), const Text('【味覚バッジ】'), ..._buildBadgeHelpRows(context, useIcons, ['flavor_dry', 'flavor_sweet', 'flavor_aromatic']), const SizedBox(height: 16), const Text('バッジを集めて、日本酒マスターを目指しましょう!'), ], ); } List _buildBadgeHelpRows(BuildContext context, bool useIcons, List ids) { final appColors = Theme.of(context).extension()!; // If badge doesn't exist, skip it safely final validIds = ids.where((id) => _badges.any((b) => b['id'] == id)); return validIds.map((id) { final badge = _badges.firstWhere((b) => b['id'] == id); return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( children: [ SizedBox( width: 24, child: useIcons ? Icon(badge['icon'], size: 16, color: appColors.brandPrimary) : Text(badge['emoji'], style: const TextStyle(fontSize: 16)) ), const SizedBox(width: 8), Expanded( child: RichText( text: TextSpan( style: Theme.of(context).textTheme.bodyMedium, children: [ TextSpan(text: '${badge['name']}: ', style: const TextStyle(fontWeight: FontWeight.bold)), TextSpan(text: badge['desc']), ], ), ), ), ], ), ); }).toList(); } }