import 'dart:async'; import 'package:flutter/material.dart'; import '../constants/app_colors.dart'; import '../services/supabase_service.dart'; import '../screens/inicial_screen.dart'; import '../screens/google_maps_screen.dart'; import '../screens/setting_screen.dart'; /// Tela principal para usuários logados com estatísticas de corrida e menu. class LogadoInicialScreen extends StatefulWidget { const LogadoInicialScreen({super.key}); @override State createState() => _LogadoInicialScreenState(); } class _LogadoInicialScreenState extends State with SingleTickerProviderStateMixin { // Variáveis de estado para controlar os dados da corrida. double progress = 0.0; // Progresso de 0.0 a 1.0 (ex: 0.5 = 50%). double targetDistance = 8.0; // Distância alvo em KM. double currentDistance = 0.0; // Distância atual percorrida. @override void initState() { super.initState(); // Simular progresso inicial _simulateProgress(); } void _simulateProgress() { Timer.periodic(const Duration(seconds: 3), (timer) { if (mounted && progress < 1.0) { setState(() { progress = (progress + 0.1).clamp(0.0, 1.0); currentDistance = targetDistance * progress; }); } else { timer.cancel(); } }); } /// Constrói o indicador de progresso circular central. Widget _buildCircularProgressIndicator() { return SizedBox( width: 200, height: 200, child: Stack( alignment: Alignment.center, children: [ // TweenAnimationBuilder cria uma animação suave quando o valor do progresso muda. TweenAnimationBuilder( tween: Tween(begin: 0.0, end: progress), duration: const Duration(milliseconds: 500), builder: (context, value, _) { return CustomPaint( size: const Size(200, 200), painter: CircularProgressPainter( progress: value, strokeWidth: 12, progressColor: AppColors.white, backgroundColor: AppColors.white.withOpacity(0.3), ), ); }, ), // Círculo interno cinza que contém o texto da porcentagem. Container( width: 170, height: 170, decoration: const BoxDecoration( color: AppColors.backgroundGrey, shape: BoxShape.circle, ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "${(progress * 100).toInt()}%", style: const TextStyle( fontSize: 36, fontWeight: FontWeight.bold, color: Colors.white, ), ), const Text( "COMPLETO", style: TextStyle(color: Colors.white70, fontSize: 12), ), ], ), ), ], ), ); } @override Widget build(BuildContext context) { final user = SupabaseService.currentUser; final userName = user?.userMetadata?['name'] ?? user?.email?.split('@')[0] ?? 'Usuário'; return Scaffold( backgroundColor: AppColors.background, body: Stack( children: [ // Static dark gray triangles Positioned( top: -50, left: -80, child: CustomPaint( size: const Size(160, 120), painter: TrianglePainter( color: Colors.grey.shade800.withOpacity(0.4), ), ), ), Positioned( top: 20, right: -60, child: CustomPaint( size: const Size(120, 90), painter: TrianglePainter( color: Colors.grey.shade800.withOpacity(0.3), ), ), ), Positioned( top: 80, left: 40, child: CustomPaint( size: const Size(140, 105), painter: TrianglePainter( color: Colors.grey.shade800.withOpacity(0.35), ), ), ), Positioned( top: 120, right: 80, child: CustomPaint( size: const Size(100, 75), painter: TrianglePainter( color: Colors.grey.shade800.withOpacity(0.25), ), ), ), Positioned( top: 160, left: -40, child: CustomPaint( size: const Size(130, 98), painter: TrianglePainter( color: Colors.grey.shade800.withOpacity(0.3), ), ), ), // User info header Positioned( top: 40, left: 20, right: 20, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Olá, $userName!', style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), Text( 'Bem-vindo de volta!', style: TextStyle(color: Colors.white70, fontSize: 14), ), ], ), Container( width: 50, height: 50, decoration: BoxDecoration( color: AppColors.buttonColor, borderRadius: BorderRadius.circular(25), ), child: const Icon( Icons.person, color: AppColors.white, size: 24, ), ), ], ), ), // 1. Indicador de progresso circular posicionado no topo central. Align( alignment: Alignment.topCenter, child: Padding( padding: const EdgeInsets.only(top: 140), child: _buildCircularProgressIndicator(), ), ), // 2. Exibição da distância (ex: 0.0 KM | 8.0 KM). Positioned( top: 360, left: 0, right: 0, child: Center( child: Container( padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 8, ), decoration: BoxDecoration( color: AppColors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(20), ), child: Text( "${currentDistance.toStringAsFixed(1)} KM | ${targetDistance.toStringAsFixed(1)} KM", style: const TextStyle( color: AppColors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), ), // 3. Contêiner de estatísticas (Passos, BPM, K/CAL) e o mapa clicável. Positioned( top: 420, left: 20, right: 20, child: Container( height: 200, decoration: BoxDecoration( color: AppColors.backgroundGrey, borderRadius: BorderRadius.circular(24), ), child: Row( children: [ // Coluna esquerda com ícones e valores de estatística. Expanded( flex: 4, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildStatItem( Icons.directions_run, "3219", "PASSOS", ), const Divider(color: Colors.white24, height: 1), _buildStatItem(Icons.favorite_border, "98", "BPM"), const Divider(color: Colors.white24, height: 1), _buildStatItem( Icons.local_fire_department, "480", "K/CAL", ), ], ), ), ), // Coluna direita contendo o mapa clicável. Expanded( flex: 6, child: GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const GoogleMapScreen(), ), ); }, child: ClipRRect( borderRadius: const BorderRadius.only( topRight: Radius.circular(24), bottomRight: Radius.circular(24), ), child: Stack( children: [ Container( color: const Color(0xFF3A3A3C), ), // Fundo do mapa. CustomPaint( size: Size.infinite, painter: MapPainter(), // Desenha as linhas e o marcador. ), // Overlay para indicar que é clicável Container( color: Colors.black.withOpacity(0.1), child: const Center( child: Icon( Icons.touch_app, color: Colors.white54, size: 40, ), ), ), ], ), ), ), ), ], ), ), ), // 4. Barra de progresso linear (centralizada acima dos botões inferiores). Positioned( bottom: 160, left: 40, // Espaçamento igual na esquerda e direita para centralizar. right: 40, child: ClipRRect( borderRadius: BorderRadius.circular(20), child: LinearProgressIndicator( value: progress, minHeight: 12, backgroundColor: AppColors.backgroundGrey.withOpacity(0.3), valueColor: const AlwaysStoppedAnimation( AppColors.white, ), ), ), ), // 5. Botões de menu inferiores. Positioned( bottom: 60, left: 0, right: 0, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildMenuButton( Icons.settings, 'Configurações', onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const SettingsScreen(), ), ); }, ), _buildMenuButton(Icons.group_outlined, 'Grupos'), _buildMenuButton(Icons.access_time, 'Histórico'), _buildMenuButton( Icons.notifications_none, 'Notificações', showBadge: true, ), _buildMenuButton(Icons.logout, 'Sair', isLogout: true), ], ), ), // 6. Botão de Bluetooth no canto superior direito. Positioned( top: 40, right: 30, child: GestureDetector( onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Bluetooth clicado!'), duration: Duration(seconds: 1), ), ); }, child: Container( padding: const EdgeInsets.all(8), decoration: const BoxDecoration( color: AppColors.backgroundGrey, shape: BoxShape.circle, ), child: Stack( children: [ const Icon( Icons.bluetooth, color: AppColors.white, size: 20, ), // Pontinho vermelho indicando status ou notificação. Positioned( left: 0, bottom: 0, child: Container( width: 6, height: 6, decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ), ], ), ), ), ), ], ), ); } /// Constrói uma linha de estatística com ícone, valor e rótulo. Widget _buildStatItem(IconData icon, String value, String label) { return Row( children: [ Icon(icon, color: Colors.white70, size: 24), const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( value, style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), Text( label, style: const TextStyle(color: Colors.white60, fontSize: 10), ), ], ), ], ); } /// Constrói um botão de menu clicável. Widget _buildMenuButton( IconData icon, String message, { bool showBadge = false, bool isLogout = false, VoidCallback? onTap, }) { return GestureDetector( onTap: onTap ?? () async { if (isLogout) { await SupabaseService.signOut(); if (mounted) { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( builder: (context) => const InicialScreen(), ), (route) => false, ); } } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('$message clicado!'), duration: const Duration(seconds: 1), ), ); } }, child: Stack( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: isLogout ? Colors.red.shade600 : AppColors.backgroundGrey, shape: BoxShape.circle, ), child: Icon(icon, color: AppColors.white, size: 24), ), // Exibe um pontinho vermelho de notificação se showBadge for true. if (showBadge) Positioned( left: 0, bottom: 0, child: Container( width: 8, height: 8, decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ), ], ), ); } } /// Pintor customizado para desenhar os triângulos estáticos. class TrianglePainter extends CustomPainter { final Color color; TrianglePainter({required this.color}); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = color ..style = PaintingStyle.fill; final path = Path(); path.moveTo(size.width / 2, 0); path.lineTo(0, size.height); path.lineTo(size.width, size.height); path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } } /// Pintor customizado para desenhar o traçado do mapa simulado. class MapPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.white38 ..strokeWidth = 3 ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; // Desenha a linha sinuosa do percurso. final path = Path(); path.moveTo(size.width * 0.1, size.height * 0.8); path.quadraticBezierTo( size.width * 0.3, size.height * 0.7, size.width * 0.4, size.height * 0.4, ); path.quadraticBezierTo( size.width * 0.5, size.height * 0.1, size.width * 0.7, size.height * 0.3, ); path.lineTo(size.width * 0.9, size.height * 0.2); // Desenha uma "estrada" mais grossa branca. final roadPaint = Paint() ..color = Colors.white ..strokeWidth = 8 ..style = PaintingStyle.stroke; final roadPath = Path(); roadPath.moveTo(size.width * 0.6, size.height * 1.1); roadPath.quadraticBezierTo( size.width * 0.7, size.height * 0.8, size.width * 1.1, size.height * 0.7, ); canvas.drawPath(path, paint); canvas.drawPath(roadPath, roadPaint); // Desenha o marcador circular (o pino no mapa). final markerPaint = Paint()..color = const Color(0xFFFF6B6B); final markerPos = Offset(size.width * 0.4, size.height * 0.4); canvas.drawCircle(markerPos, 6, markerPaint); // Desenha o centro branco do marcador. final innerPaint = Paint()..color = Colors.white; canvas.drawCircle(markerPos, 2, innerPaint); } @override bool shouldRepaint(CustomPainter oldDelegate) => false; } /// Pintor customizado para desenhar o arco de progresso circular. class CircularProgressPainter extends CustomPainter { final double progress; final double strokeWidth; final Color progressColor; final Color backgroundColor; CircularProgressPainter({ required this.progress, required this.strokeWidth, required this.progressColor, required this.backgroundColor, }); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = (size.width - strokeWidth) / 2; // Desenha o círculo de fundo (cinza transparente). final backgroundPaint = Paint() ..color = backgroundColor ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke; canvas.drawCircle(center, radius, backgroundPaint); // Desenha o arco de progresso (branco). final progressPaint = Paint() ..color = progressColor ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; const startAngle = -3.14159265359 / 2; // Começa no topo (-90 graus). final sweepAngle = 2 * 3.14159265359 * progress; // Define o tamanho do arco com base no progresso. canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, sweepAngle, false, progressPaint, ); } @override bool shouldRepaint(CircularProgressPainter oldDelegate) => oldDelegate.progress != progress; }