import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'dart:math' as math; import '../../../common/constant/app_constant.dart'; import '../../../common/theme/theme.dart'; @RoutePage() class PointPage extends StatefulWidget { const PointPage({super.key}); @override State createState() => _PointPageState(); } class _PointPageState extends State { int _currentPage = 0; final PageController _pageController = PageController(viewportFraction: 1.0); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Column( children: [ // Pink Header with overlapping elements Stack( clipBehavior: Clip.none, children: [ // Pink Background Container( height: 320, width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ AppColor.primary.withOpacity(0.8), AppColor.primary, ], ), ), child: SafeArea( child: Padding( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Back Button Container( width: 56, height: 56, decoration: BoxDecoration( color: Colors.white.withOpacity(0.3), shape: BoxShape.circle, ), child: IconButton( icon: const Icon( Icons.arrow_back, color: Colors.white, size: 28, ), onPressed: () => Navigator.pop(context), ), ), const SizedBox(height: 32), // Title Text( 'Kelola ${AppConstant.poinName} kamu!', style: AppStyle.h3.copyWith( color: AppColor.white, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), // Subtitle Text( 'Bisa kumpulin dan tukar dari sini.', style: AppStyle.md.copyWith( color: AppColor.white.withOpacity(0.9), ), ), ], ), ), ), ), // Point Card - Overlapping Positioned( top: 280, left: 24, right: 24, child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 56, height: 56, decoration: BoxDecoration( color: AppColor.primary, shape: BoxShape.circle, ), child: const Icon( Icons.card_giftcard, color: Colors.white, size: 32, ), ), const SizedBox(width: 16), Text( '50 ${AppConstant.poinName}', style: AppStyle.h4.copyWith( color: AppColor.primary, fontWeight: FontWeight.bold, ), ), ], ), ), ), ], ), // Black Section const SizedBox(height: 100), Container( color: Colors.white, width: double.infinity, child: Column( children: [ // Title Section Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( children: [ Text( 'Tukar ${AppConstant.poinName} buat seru-seruan', style: AppStyle.h4.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), ], ), ), const SizedBox(height: 40), // PageView - Show 2 items per page SizedBox( height: 340, child: PageView( controller: _pageController, onPageChanged: (index) { setState(() { _currentPage = index; }); }, children: [ // Page 1 - 2 cards Row( children: [ Expanded( child: _buildRewardCard( title: 'Main Gift Arena\nsekarang!', subtitle: 'Dapetin s.d. 1jt Coins!', buttonText: 'Pakai 50 💎', isWheel: true, ), ), Expanded( child: _buildRewardCard( title: 'Putar untuk\nHarapan', subtitle: 'GoPay Pet', buttonText: 'Pakai 5 💎', isWheel: false, ), ), ], ), // Page 2 - 2 cards Row( children: [ Expanded( child: _buildRewardCard( title: 'Spin & Win\nHadiah!', subtitle: 'Kesempatan menang besar!', buttonText: 'Pakai 30 💎', isWheel: true, ), ), Expanded( child: _buildRewardCard( title: 'Lucky Draw\nBerhadiah', subtitle: 'Coba keberuntungan!', buttonText: 'Pakai 20 💎', isWheel: false, ), ), ], ), // Page 3 - 1 card Row( children: [ Expanded( child: _buildRewardCard( title: 'Mega Prize\nWheel', subtitle: 'Hadiah hingga 10jt!', buttonText: 'Pakai 100 💎', isWheel: true, ), ), const Spacer(), // Empty space for alignment ], ), ], ), ), const SizedBox(height: 20), // Indicators - 3 pages Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(3, (index) { return AnimatedContainer( duration: const Duration(milliseconds: 300), margin: const EdgeInsets.symmetric(horizontal: 4), width: _currentPage == index ? 28 : 8, height: 8, decoration: BoxDecoration( color: _currentPage == index ? AppColor.primary : Colors.grey.withOpacity(0.3), borderRadius: BorderRadius.circular(4), ), ); }), ), const SizedBox(height: 40), // Bottom Text Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( children: [ Text( 'Ada banyak cara dapet ${AppConstant.poinName}', style: AppStyle.h5.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'Mulai dari main game sampai nonton video.', style: AppStyle.sm.copyWith( color: AppColor.textLight, ), textAlign: TextAlign.center, ), ], ), ), const SizedBox(height: 60), ], ), ), ], ), ), ); } Widget _buildRewardCard({ required String title, required String subtitle, required String buttonText, required bool isWheel, }) { return Padding( padding: const EdgeInsets.only(left: 16), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 20), decoration: BoxDecoration( color: const Color(0xFF2D2D2D), borderRadius: BorderRadius.circular(24), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Icon Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, color: isWheel ? const Color(0xFF4FC3F7) : const Color(0xFFFFC107), boxShadow: [ BoxShadow( color: (isWheel ? const Color(0xFF4FC3F7) : const Color(0xFFFFC107)) .withOpacity(0.3), blurRadius: 20, spreadRadius: 5, ), ], ), child: Center( child: Container( width: 120, height: 120, decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: isWheel ? CustomPaint(painter: WheelPainter()) : CustomPaint(painter: CoinPainter()), ), ), ), const SizedBox(height: 20), Text( title, style: AppStyle.md.copyWith( color: AppColor.white, fontWeight: FontWeight.bold, height: 1.3, ), textAlign: TextAlign.center, ), const SizedBox(height: 6), Text( subtitle, style: AppStyle.sm.copyWith(color: AppColor.textLight), textAlign: TextAlign.center, ), const SizedBox(height: 18), ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primary, padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 12, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 0, ), child: Text( buttonText, style: AppStyle.sm.copyWith( color: AppColor.white, fontWeight: FontWeight.bold, ), ), ), ], ), ), ); } } class WheelPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 2; // Draw wheel segments final paint = Paint()..style = PaintingStyle.fill; const segments = 8; final sweepAngle = (2 * math.pi) / segments; for (int i = 0; i < segments; i++) { paint.color = i.isEven ? const Color(0xFF2196F3) : const Color(0xFF90CAF9); canvas.drawArc( Rect.fromCircle(center: center, radius: radius * 0.9), i * sweepAngle, sweepAngle, true, paint, ); } // Draw center circle paint.color = const Color(0xFFFFEB3B); canvas.drawCircle(center, radius * 0.25, paint); // Draw pointer at top final pointerPaint = Paint() ..color = const Color(0xFFE91E63) ..style = PaintingStyle.fill; final pointerPath = Path(); pointerPath.moveTo(center.dx, radius * 0.15); pointerPath.lineTo(center.dx - radius * 0.15, 0); pointerPath.lineTo(center.dx + radius * 0.15, 0); pointerPath.close(); canvas.drawPath(pointerPath, pointerPaint); // Draw white border on pointer final borderPaint = Paint() ..color = Colors.white ..style = PaintingStyle.stroke ..strokeWidth = 3; canvas.drawPath(pointerPath, borderPaint); // Draw dots around edge paint.color = const Color(0xFF4FC3F7); for (int i = 0; i < 12; i++) { final angle = (i * 2 * math.pi) / 12; final x = center.dx + radius * 0.95 * math.cos(angle); final y = center.dy + radius * 0.95 * math.sin(angle); canvas.drawCircle(Offset(x, y), 4, paint); } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } class CoinPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 2; // Draw outer ring final ringPaint = Paint() ..color = const Color(0xFFD4A418) ..style = PaintingStyle.stroke ..strokeWidth = 8; canvas.drawCircle(center, radius * 0.85, ringPaint); // Draw inner circle final innerPaint = Paint() ..color = const Color(0xFFFFC107) ..style = PaintingStyle.fill; canvas.drawCircle(center, radius * 0.75, innerPaint); // Draw center ring symbol final centerRingPaint = Paint() ..color = const Color(0xFFD4A418) ..style = PaintingStyle.stroke ..strokeWidth = 6; canvas.drawCircle(center, radius * 0.35, centerRingPaint); // Draw small colored dots around final colors = [ Colors.red, Colors.blue, Colors.green, Colors.purple, Colors.orange, Colors.pink, ]; for (int i = 0; i < 6; i++) { final angle = (i * 2 * math.pi) / 6; final x = center.dx + radius * 0.6 * math.cos(angle); final y = center.dy + radius * 0.6 * math.sin(angle); final dotPaint = Paint() ..color = colors[i] ..style = PaintingStyle.fill; canvas.drawCircle(Offset(x, y), 6, dotPaint); } // Draw numbers around edge final textPainter = TextPainter( textDirection: TextDirection.ltr, textAlign: TextAlign.center, ); for (int i = 0; i < 12; i++) { final angle = (i * 2 * math.pi) / 12 - math.pi / 2; final x = center.dx + radius * 0.85 * math.cos(angle); final y = center.dy + radius * 0.85 * math.sin(angle); textPainter.text = TextSpan( text: '${(i + 1) * 10}', style: const TextStyle( color: Color(0xFFD4A418), fontSize: 10, fontWeight: FontWeight.bold, ), ); textPainter.layout(); textPainter.paint( canvas, Offset(x - textPainter.width / 2, y - textPainter.height / 2), ); } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }