diff --git a/sojorn_app/lib/widgets/post/post_actions.dart b/sojorn_app/lib/widgets/post/post_actions.dart index 69c2ae3..cd5d330 100644 --- a/sojorn_app/lib/widgets/post/post_actions.dart +++ b/sojorn_app/lib/widgets/post/post_actions.dart @@ -8,6 +8,7 @@ import '../../providers/api_provider.dart'; import '../../theme/app_theme.dart'; import '../sojorn_snackbar.dart'; import '../reactions/reaction_strip.dart'; +import '../reactions/reaction_picker.dart'; /// Post actions with a vibrant, clear, and energetic design. /// @@ -137,6 +138,20 @@ class _PostActionsState extends ConsumerState { } } + void _showReactionPicker() { + showDialog( + context: context, + builder: (context) => ReactionPicker( + onReactionSelected: (emoji) { + _toggleReaction(emoji); + }, + onClosed: () { + // Optional: Handle picker closed without selection + }, + ), + ); + } + Future _toggleReaction(String emoji) async { final previousCounts = Map.from(_reactionCounts); final previousMine = Set.from(_myReactions); @@ -219,7 +234,7 @@ class _PostActionsState extends ConsumerState { myReactions: _myReactions, reactionUsers: {}, onToggle: (emoji) => _toggleReaction(emoji), - onAdd: () => _toggleReaction('❤️'), // Default to heart for now + onAdd: _showReactionPicker, // Show picker instead of default heart ), const SizedBox(height: 16), // Actions row - left aligned diff --git a/sojorn_app/lib/widgets/reactions/reaction_picker.dart b/sojorn_app/lib/widgets/reactions/reaction_picker.dart new file mode 100644 index 0000000..8a48552 --- /dev/null +++ b/sojorn_app/lib/widgets/reactions/reaction_picker.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import '../../theme/app_theme.dart'; + +class ReactionPicker extends StatefulWidget { + final Function(String) onReactionSelected; + final VoidCallback? onClosed; + + const ReactionPicker({ + super.key, + required this.onReactionSelected, + this.onClosed, + }); + + @override + State createState() => _ReactionPickerState(); +} + +class _ReactionPickerState extends State { + static const List _commonReactions = [ + '❤️', '👍', '😂', '😮', '😢', '😡', + '🎉', '🔥', '👏', '🙏', '💯', '🤔', + '😍', '🤣', '😊', '👌', '🙌', '💪', + '🎯', '⭐', '✨', '🌟', '💫', '☀️', + ]; + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppTheme.cardSurface, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppTheme.navyBlue.withValues(alpha: 0.2), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.2), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Header + Row( + children: [ + Text( + 'Add Reaction', + style: GoogleFonts.inter( + color: AppTheme.navyBlue, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + const Spacer(), + IconButton( + onPressed: () { + Navigator.of(context).pop(); + widget.onClosed?.call(); + }, + icon: Icon( + Icons.close, + color: AppTheme.textSecondary, + size: 20, + ), + ), + ], + ), + const SizedBox(height: 16), + + // Emoji grid + GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 6, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + childAspectRatio: 1, + ), + itemCount: _commonReactions.length, + itemBuilder: (context, index) { + final emoji = _commonReactions[index]; + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + widget.onReactionSelected(emoji); + }, + borderRadius: BorderRadius.circular(12), + child: Container( + decoration: BoxDecoration( + color: AppTheme.navyBlue.withValues(alpha: 0.05), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: AppTheme.navyBlue.withValues(alpha: 0.1), + width: 1, + ), + ), + child: Center( + child: Text( + emoji, + style: const TextStyle(fontSize: 24), + ), + ), + ), + ), + ); + }, + ), + const SizedBox(height: 16), + ], + ), + ), + ); + } +}