Files

116 lines
3.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import '../core/theme/app_theme.dart';
class VoteButtons extends StatefulWidget {
final int upvotes;
final int downvotes;
final bool? userVote;
final VoidCallback onUpvote;
final VoidCallback onDownvote;
const VoteButtons({
super.key,
required this.upvotes,
required this.downvotes,
this.userVote,
required this.onUpvote,
required this.onDownvote,
});
@override
State<VoteButtons> createState() => _VoteButtonsState();
}
class _VoteButtonsState extends State<VoteButtons> {
bool _animatingUp = false;
bool _animatingDown = false;
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
_buildButton(
icon: Icons.thumb_up_outlined,
activeIcon: Icons.thumb_up,
count: widget.upvotes,
isActive: widget.userVote == true,
color: VoIdeaColors.success,
onTap: () {
setState(() => _animatingUp = true);
widget.onUpvote();
Future.delayed(300.ms, () {
if (mounted) setState(() => _animatingUp = false);
});
},
animating: _animatingUp,
),
const SizedBox(width: 16),
_buildButton(
icon: Icons.thumb_down_outlined,
activeIcon: Icons.thumb_down,
count: widget.downvotes,
isActive: widget.userVote == false,
color: VoIdeaColors.error,
onTap: () {
setState(() => _animatingDown = true);
widget.onDownvote();
Future.delayed(300.ms, () {
if (mounted) setState(() => _animatingDown = false);
});
},
animating: _animatingDown,
),
],
);
}
Widget _buildButton({
required IconData icon,
required IconData activeIcon,
required int count,
required bool isActive,
required Color color,
required VoidCallback onTap,
required bool animating,
}) {
return GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: 200.ms,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: isActive ? color.withOpacity(0.1) : Colors.transparent,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: isActive ? color : VoIdeaColors.muted.withOpacity(0.3),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
isActive ? activeIcon : icon,
size: 18,
color: isActive ? color : VoIdeaColors.muted,
).animate(target: animating ? 1 : 0).scale(
begin: const Offset(1, 1),
end: const Offset(1.3, 1.3),
duration: 200.ms,
),
const SizedBox(width: 4),
Text(
count.toString(),
style: TextStyle(
color: isActive ? color : VoIdeaColors.muted,
fontWeight: isActive ? FontWeight.w600 : FontWeight.normal,
),
),
],
),
),
);
}
}