import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import '../../../../core/services/rag_service.dart'; /// Enhanced chat input widget with suggestions and mode selection class ChatInput extends StatefulWidget { final TextEditingController controller; final VoidCallback onSend; final ValueChanged? onModeChanged; final TutorMode currentMode; final bool isLoading; final List suggestions; final VoidCallback? onClear; const ChatInput({ super.key, required this.controller, required this.onSend, this.onModeChanged, this.currentMode = TutorMode.explanation, this.isLoading = false, this.suggestions = const [], this.onClear, }); @override State createState() => _ChatInputState(); } class _ChatInputState extends State { bool _showSuggestions = false; bool _isExpanded = false; final FocusNode _focusNode = FocusNode(); @override void initState() { super.initState(); _focusNode.addListener(_onFocusChange); } @override void dispose() { _focusNode.removeListener(_onFocusChange); _focusNode.dispose(); super.dispose(); } void _onFocusChange() { setState(() { _showSuggestions = _focusNode.hasFocus && widget.suggestions.isNotEmpty; }); } @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Container( padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( color: cs.surface.withOpacity(0.98), borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, -5), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Mode selector _buildModeSelector(context), const SizedBox(height: 12), // Input field with send button _buildInputField(context), // Suggestions if (_showSuggestions) ...[ const SizedBox(height: 8), _buildSuggestions(context), ], ], ), ).animate().slideY(begin: 1.0, end: 0.0, duration: const Duration(milliseconds: 300)); } Widget _buildModeSelector(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey[200]!, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Modo de Tutoria', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Colors.grey[700], ), ), const SizedBox(height: 8), Row( children: TutorMode.values.map((mode) => _buildModeButton(mode)).toList(), ), ], ), ); } Widget _buildModeButton(TutorMode mode) { final isSelected = widget.currentMode == mode; final modeInfo = _getModeInfo(mode); return Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4.0), child: InkWell( onTap: () => widget.onModeChanged?.call(mode), borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0), decoration: BoxDecoration( gradient: isSelected ? LinearGradient( colors: [ modeInfo['color'] as Color, modeInfo['colorDark'] as Color, ], ) : null, color: isSelected ? null : Colors.transparent, borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected ? Colors.transparent : Colors.grey[300]!, ), ), child: Column( children: [ Icon( modeInfo['icon'] as IconData, size: 20, color: isSelected ? Colors.white : Colors.grey[600], ), const SizedBox(height: 4), Text( modeInfo['label'] as String, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: isSelected ? Colors.white : Colors.grey[600], ), textAlign: TextAlign.center, ), ], ), ), ), ), ); } Widget _buildInputField(BuildContext context) { final cs = Theme.of(context).colorScheme; return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), gradient: LinearGradient( colors: [ cs.surfaceContainerHighest, cs.surface, ], ), border: Border.all( color: cs.outline.withOpacity(0.3), ), ), child: Row( children: [ // Text field Expanded( child: TextField( controller: widget.controller, focusNode: _focusNode, maxLines: _isExpanded ? 5 : 1, style: TextStyle( fontSize: 16, color: cs.onSurface, ), decoration: InputDecoration( hintText: 'Faça sua pergunta sobre o conteúdo...', hintStyle: TextStyle( color: Colors.grey[500], ), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), onSubmitted: (_) => _handleSend(), ), ), // Action buttons Padding( padding: const EdgeInsets.only(right: 8.0), child: Row( mainAxisSize: MainAxisSize.min, children: [ // Expand/Collapse button if (widget.controller.text.isNotEmpty) ...[ IconButton( onPressed: () => setState(() => _isExpanded = !_isExpanded), icon: Icon( _isExpanded ? Icons.compress : Icons.expand, color: Colors.grey[600], size: 20, ), tooltip: _isExpanded ? 'Reduzir' : 'Expandir', ), ], // Clear button if (widget.controller.text.isNotEmpty) IconButton( onPressed: () { widget.controller.clear(); widget.onClear?.call(); setState(() { _isExpanded = false; _showSuggestions = false; }); }, icon: Icon( Icons.clear, color: Colors.grey[600], size: 20, ), tooltip: 'Limpar', ), // Send button Container( width: 48, height: 48, decoration: BoxDecoration( gradient: widget.controller.text.isNotEmpty ? LinearGradient( colors: [ cs.primary, cs.primary.withOpacity(0.85), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : null, color: widget.controller.text.isNotEmpty ? null : Colors.grey[300], borderRadius: BorderRadius.circular(24), boxShadow: widget.controller.text.isNotEmpty ? [ BoxShadow( color: const Color(0xFF82C9BD).withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), ] : null, ), child: IconButton( onPressed: widget.controller.text.isNotEmpty && !widget.isLoading ? _handleSend : null, icon: widget.isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white, ), ), ) : Icon( Icons.send, color: Colors.white, size: 20, ), ), ), ], ), ), ], ), ); } Widget _buildSuggestions(BuildContext context) { return Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey[200]!, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.lightbulb, size: 16, color: Colors.grey[600], ), const SizedBox(width: 6), Text( 'Sugestões', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Colors.grey[700], ), ), ], ), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 4, children: widget.suggestions.take(6).map((suggestion) { return InkWell( onTap: () { widget.controller.text = suggestion; _focusNode.requestFocus(); }, borderRadius: BorderRadius.circular(16), child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [ const Color(0xFF82C9BD).withOpacity(0.1), const Color(0xFF6BA5A0).withOpacity(0.1), ], ), borderRadius: BorderRadius.circular(16), border: Border.all( color: const Color(0xFF82C9BD).withOpacity(0.3), ), ), child: Text( suggestion, style: TextStyle( fontSize: 12, color: const Color(0xFF82C9BD), fontWeight: FontWeight.w500, ), ), ), ); }).toList(), ), ], ), ).animate().fadeIn(duration: const Duration(milliseconds: 200)); } Map _getModeInfo(TutorMode mode) { switch (mode) { case TutorMode.explanation: return { 'label': 'Explicação', 'icon': Icons.school, 'color': const Color(0xFF82C9BD), 'colorDark': const Color(0xFF6BA5A0), }; case TutorMode.tutor: return { 'label': 'Tutor', 'icon': Icons.psychology, 'color': const Color(0xFFF68D2D), 'colorDark': const Color(0xFFE67E22), }; case TutorMode.exploration: return { 'label': 'Exploração', 'icon': Icons.explore, 'color': const Color(0xFF9C27B0), 'colorDark': const Color(0xFF7B1FA2), }; } } void _handleSend() { if (widget.controller.text.trim().isNotEmpty && !widget.isLoading) { widget.onSend(); setState(() { _isExpanded = false; _showSuggestions = false; }); } } }