import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../models/history_entry_model.dart'; import '../models/word_model.dart'; import '../services/words_repository.dart'; import 'gradient_star_badge.dart'; class WordCardWidget extends StatefulWidget { final WordItem word; final VoidCallback? onNext; final VoidCallback? onPrevious; final VoidCallback? onRandom; final String? positionTitle; // Optional title for spread positions const WordCardWidget({ super.key, required this.word, this.onNext, this.onPrevious, this.onRandom, this.positionTitle, }); @override State createState() => _WordCardWidgetState(); } class _WordCardWidgetState extends State { final _repo = WordsRepository(); bool _savedToHistory = false; @override void didUpdateWidget(covariant WordCardWidget oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.word.id != widget.word.id || oldWidget.word.sessionNumber != widget.word.sessionNumber) { _savedToHistory = false; } } Color _getPosColor(String pos) { switch (pos.toLowerCase()) { case 'существительное': return const Color(0xFF64B5F6); // Celestial Blue case 'глагол': return const Color(0xFF81C784); // Vital Green case 'прилагательное': return const Color(0xFFFFD54F); // Golden case 'наречие': case 'наречие-местоимение': return const Color(0xFFBA68C8); // Mystic Violet case 'местоимение': case 'местоименное прил.': return const Color(0xFF4DD0E1); // Cyan case 'предлог': case 'союз': case 'частица': return const Color(0xFFFF8A65); // Coral Ember default: return const Color(0xFF90A4AE); } } Future _recordToHistory() async { if (_savedToHistory) return; final entry = HistoryEntry( id: DateTime.now().millisecondsSinceEpoch.toString(), timestamp: DateTime.now(), word: widget.word.word, sessionNumber: widget.word.sessionNumber, partOfSpeech: widget.word.partOfSpeech, symbolicMeaning: widget.word.description, readingType: widget.positionTitle ?? 'Жребий номера', positionTitle: widget.positionTitle, ); await _repo.addHistoryEntry(entry); if (!mounted) return; setState(() => _savedToHistory = true); HapticFeedback.mediumImpact(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const GradientStar(size: 18), const SizedBox(width: 10), Expanded( child: Text('Символ «${widget.word.word}» сохранён в историю'), ), ], ), duration: const Duration(seconds: 2), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ); } void _copyToClipboard(BuildContext context) { final now = DateTime.now(); final day = now.day.toString().padLeft(2, '0'); final month = now.month.toString().padLeft(2, '0'); final year = now.year.toString(); final hour = now.hour.toString().padLeft(2, '0'); final min = now.minute.toString().padLeft(2, '0'); final text = '✨ Оракул 999 — Толкование символа ✨\n' 'Дата и время: $day.$month.$year $hour:$min\n' 'Знак №${widget.word.formattedSessionNumber}: ${widget.word.word.toUpperCase()}\n' 'Аспект: ${widget.word.partOfSpeech} • ${widget.word.category}\n\n' '🔮 Символическое значение:\n${widget.word.description}'; Clipboard.setData(ClipboardData(text: text)); HapticFeedback.lightImpact(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const GradientStar(size: 18), const SizedBox(width: 10), Expanded(child: Text('Толкование «${widget.word.word}» скопировано')), ], ), duration: const Duration(seconds: 2), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; final posColor = _getPosColor(widget.word.partOfSpeech); return Card( elevation: 8, shadowColor: const Color(0xFFFFD54F).withValues(alpha: 0.18), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), side: BorderSide( color: const Color(0xFFFFD54F).withValues(alpha: 0.25), width: 1.2, ), ), clipBehavior: Clip.antiAlias, child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: isDark ? [ const Color(0xFF1E2138), const Color(0xFF121424), ] : [ const Color(0xFFF9F9FF), const Color(0xFFEFF1F9), ], ), ), padding: const EdgeInsets.all(22), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ // Optional spread position banner (e.g. "Исток / Прошлое") if (widget.positionTitle != null) ...[ Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: const Color(0xFFFFD54F).withValues(alpha: 0.15), borderRadius: BorderRadius.circular(10), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.4), ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const GradientStar(size: 14), const SizedBox(width: 6), Text( widget.positionTitle!, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Color(0xFFFFD54F), letterSpacing: 0.5, ), ), ], ), ), ], // Top Row: Gradient Star Number Badge and Action Buttons Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GradientStarBadge( text: '#${widget.word.formattedSessionNumber} / 999', size: 18, ), Row( children: [ IconButton( tooltip: 'Скопировать толкование', icon: const Icon(Icons.copy_rounded, size: 20), onPressed: () => _copyToClipboard(context), ), IconButton( tooltip: _savedToHistory ? 'Сохранено в историю' : 'Сохранить в историю', icon: Icon( _savedToHistory ? Icons.bookmark_added_rounded : Icons.bookmark_add_outlined, color: _savedToHistory ? const Color(0xFFFFD54F) : null, size: 22, ), onPressed: _recordToHistory, ), ], ), ], ), const SizedBox(height: 14), // Big Word Title Center( child: Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Text( widget.word.word.toUpperCase(), textAlign: TextAlign.center, style: theme.textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.w900, letterSpacing: 1.5, color: isDark ? const Color(0xFFFFF9C4) : const Color(0xFF1B1D30), ), ), ), ), // Part of Speech & Category Badges Center( child: Wrap( spacing: 8, runSpacing: 6, alignment: WrapAlignment.center, children: [ Chip( avatar: Icon(Icons.auto_awesome, size: 14, color: posColor), label: Text( widget.word.partOfSpeech, style: TextStyle( fontWeight: FontWeight.w600, fontSize: 12, color: posColor, ), ), backgroundColor: posColor.withValues(alpha: 0.12), side: BorderSide(color: posColor.withValues(alpha: 0.3)), padding: const EdgeInsets.symmetric(horizontal: 4), ), if (widget.word.category.isNotEmpty) Chip( label: Text( widget.word.category, style: TextStyle( fontSize: 12, color: isDark ? Colors.white70 : Colors.black87, ), ), backgroundColor: isDark ? Colors.white.withValues(alpha: 0.08) : Colors.black.withValues(alpha: 0.05), side: BorderSide.none, padding: const EdgeInsets.symmetric(horizontal: 2), ), ], ), ), const SizedBox(height: 16), Divider( height: 1, color: isDark ? Colors.white12 : Colors.black12, ), const SizedBox(height: 14), // Symbolic Divination Meaning Box Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isDark ? const Color(0xFF141729) : const Color(0xFFFFFFFF), borderRadius: BorderRadius.circular(16), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.2), ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: isDark ? 0.2 : 0.05), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const GradientStar(size: 16), const SizedBox(width: 8), Text( 'СИМВОЛИЧЕСКОЕ ЗНАЧЕНИЕ', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w900, letterSpacing: 1.0, color: const Color(0xFFFFD54F), ), ), ], ), const SizedBox(height: 10), Text( widget.word.description, style: theme.textTheme.bodyLarge?.copyWith( height: 1.5, fontSize: 14.5, color: isDark ? const Color(0xFFE2E4F0) : const Color(0xFF2C3042), ), ), ], ), ), const SizedBox(height: 18), // Navigation Controls Row Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: widget.onPrevious, icon: const Icon(Icons.arrow_back_ios_new_rounded, size: 14), label: const Text('Пред.'), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), ), ), const SizedBox(width: 8), IconButton.filledTonal( tooltip: 'Случайный жребий', onPressed: widget.onRandom, icon: const GradientStar(size: 20), style: IconButton.styleFrom( padding: const EdgeInsets.all(12), backgroundColor: const Color(0xFF2A2D4A), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide( color: const Color(0xFFFFD54F).withValues(alpha: 0.3), ), ), ), ), const SizedBox(width: 8), Expanded( child: FilledButton.icon( onPressed: widget.onNext, icon: const Text('След.'), label: const Icon(Icons.arrow_forward_ios_rounded, size: 14), style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), ), ), ], ), ], ), ), ); } }