import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:lucide_icons/lucide_icons.dart'; import '../../../models/sake_item.dart'; import '../../../theme/app_colors.dart'; import '../../../constants/app_constants.dart'; import '../../../providers/theme_provider.dart'; import '../../../services/mbti_compatibility_service.dart'; String _formatRecordedDate(DateTime date) { return '${date.year}年${date.month}月${date.day}日に記録'; } /// 銘柄名・蔵元/都道府県・タグ・AI確信度バッジ・MBTI相性バッジ・キャッチコピーを表示するセクション class SakeBasicInfoSection extends ConsumerWidget { final SakeItem sake; final VoidCallback onTapName; final VoidCallback onTapBrewery; final VoidCallback onTapTags; final void Function(BuildContext context, CompatibilityResult result, AppColors appColors) onTapMbtiCompatibility; const SakeBasicInfoSection({ super.key, required this.sake, required this.onTapName, required this.onTapBrewery, required this.onTapTags, required this.onTapMbtiCompatibility, }); @override Widget build(BuildContext context, WidgetRef ref) { final appColors = Theme.of(context).extension()!; // AI Confidence Logic (Theme Aware) final score = sake.metadata.aiConfidence ?? 0; final Color confidenceColor = score >= AppConstants.confidenceScoreHigh ? appColors.brandPrimary : score >= AppConstants.confidenceScoreMedium ? appColors.textSecondary : appColors.textTertiary; // MBTI Compatibility final userProfile = ref.watch(userProfileProvider); final mbtiType = userProfile.mbti; final mbtiResult = (mbtiType != null && mbtiType.isNotEmpty) ? MBTICompatibilityService.calculateCompatibility(mbtiType, sake) : null; final showMbti = mbtiResult != null && mbtiResult.hasResult; final badgeColor = showMbti ? (mbtiResult.starRating >= 4 ? appColors.brandPrimary : mbtiResult.starRating >= 3 ? appColors.textSecondary : appColors.textTertiary) : null; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 変更1: AI確信度 + MBTI相性 を横並び1行に統合 if ((sake.metadata.aiConfidence != null && sake.itemType != ItemType.set) || showMbti) Center( child: Padding( padding: const EdgeInsets.only(bottom: 16), child: Wrap( alignment: WrapAlignment.center, spacing: 8, runSpacing: 8, children: [ if (sake.metadata.aiConfidence != null && sake.itemType != ItemType.set) Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: confidenceColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20), border: Border.all(color: confidenceColor.withValues(alpha: 0.4)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(LucideIcons.sparkles, size: 12, color: confidenceColor), const SizedBox(width: 4), Text( 'AI $score%', style: TextStyle( color: confidenceColor, fontWeight: FontWeight.bold, fontSize: 11, ), ), ], ), ), if (showMbti) GestureDetector( onTap: () => onTapMbtiCompatibility(context, mbtiResult, appColors), child: Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: badgeColor!.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20), border: Border.all(color: badgeColor.withValues(alpha: 0.4)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(LucideIcons.brainCircuit, size: 12, color: badgeColor), const SizedBox(width: 4), Text( '$mbtiType ${mbtiResult.starDisplay}', style: TextStyle( color: badgeColor, fontWeight: FontWeight.bold, fontSize: 11, letterSpacing: 0.5, ), ), ], ), ), ), ], ), ), ), // 変更2: 銘柄名から鉛筆アイコンを除去(タップで編集は維持) Center( child: InkWell( onTap: onTapName, borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Text( sake.displayData.displayName, style: Theme.of(context).textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, letterSpacing: 1.2, ), textAlign: TextAlign.center, ), ), ), ), const SizedBox(height: 6), // 変更2: 酒蔵 / 都道府県 — 区切りを · に変更・鉛筆アイコン除去 if (sake.itemType != ItemType.set) Center( child: InkWell( onTap: onTapBrewery, borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Text( '${sake.displayData.displayBrewery} · ${sake.displayData.displayPrefecture}', style: Theme.of(context).textTheme.bodyLarge?.copyWith( color: appColors.textSecondary, fontWeight: FontWeight.w400, ), textAlign: TextAlign.center, ), ), ), ), const SizedBox(height: 8), // 記録日 if (sake.itemType != ItemType.set) Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(LucideIcons.calendarDays, size: 11, color: appColors.textTertiary), const SizedBox(width: 4), Text( _formatRecordedDate(sake.metadata.createdAt), style: TextStyle(fontSize: 11, color: appColors.textTertiary), ), ], ), ), const SizedBox(height: 20), // キャッチコピー(位置を銘柄名直下に移動して存在感を強調) if (sake.displayData.catchCopy != null && sake.itemType != ItemType.set) Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( sake.displayData.catchCopy!, style: GoogleFonts.zenOldMincho( fontSize: 22, height: 1.6, fontWeight: FontWeight.w500, color: Theme.of(context).brightness == Brightness.dark ? Colors.white70 : appColors.brandPrimary.withValues(alpha: 0.8), ), textAlign: TextAlign.center, ), ), ), const SizedBox(height: 20), // タグ — pill 形状・中央揃え if (sake.hiddenSpecs.flavorTags.isNotEmpty) Center( child: InkWell( onTap: onTapTags, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Wrap( alignment: WrapAlignment.center, spacing: 6, runSpacing: 6, children: sake.hiddenSpecs.flavorTags.map((tag) => Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: appColors.brandPrimary.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(20), border: Border.all( color: appColors.brandPrimary.withValues(alpha: 0.2), ), ), child: Text( tag, style: TextStyle( fontSize: 11, color: appColors.brandPrimary, fontWeight: FontWeight.w500, ), ), )).toList(), ), ), ), ), ], ); } }