import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../constants/app_colors.dart'; import '../constants/app_strings.dart'; import '../services/supabase_service.dart'; import 'setting_screen.dart'; import 'bluetooth_connection_screen.dart'; import 'google_map_screen.dart'; class LogadoScreen extends StatefulWidget { const LogadoScreen({super.key}); @override State createState() => _LogadoScreenState(); } class _LogadoScreenState extends State { // Estado dinâmico do utilizador double _dailyGoal = 0.0; double _currentDistance = 0.0; double _bestDistance = 0.0; // Será atualizado do banco double _bestSpeed = 0.0; // Será atualizado do banco int _steps = 0; int _totalTimeMinutes = 0; double get _progress => _dailyGoal > 0 ? (_currentDistance / _dailyGoal).clamp(0.0, 1.0) : 0.0; @override void initState() { super.initState(); _loadUserData(); } @override void didChangeDependencies() { super.didChangeDependencies(); // Recarregar dados quando a tela ganha foco (após retornar de uma corrida) WidgetsBinding.instance.addPostFrameCallback((_) { _loadUserData(); }); } Future _loadUserData() async { final prefs = await SharedPreferences.getInstance(); final lastGoalDate = prefs.getString('last_goal_date'); final today = DateTime.now().toIso8601String().split('T')[0]; // Buscar estatísticas do usuário do banco de dados try { final userStats = await SupabaseService.getUserStats(); // Buscar corridas de hoje para calcular distância total await _loadTodayDistance(); setState(() { // Reset meta se o dia mudou if (lastGoalDate != today) { _dailyGoal = 0.0; prefs.remove('daily_goal'); } else { _dailyGoal = prefs.getDouble('daily_goal') ?? 0.0; } // Atualizar records do banco de dados if (userStats != null) { // Converter distância de metros para km (se necessário) _bestDistance = (userStats['max_distance'] ?? 0.0) / 1000.0; // Converter pace para velocidade (km/h) // Pace é minutos por km, velocidade é km/h // Velocidade = 60 / pace final bestPace = userStats['best_pace'] ?? 0.0; _bestSpeed = bestPace > 0 ? (60.0 / bestPace) : 0.0; } else { // Manter valores padrão se não houver dados _bestDistance = 0.0; _bestSpeed = 0.0; } // Calcular passos com base na distância (7 passos a cada 5 metros) _steps = ((_currentDistance * 1000) / 5 * 7).round(); _totalTimeMinutes = 0; }); } catch (e) { // Em caso de erro, manter valores padrão setState(() { if (lastGoalDate != today) { _dailyGoal = 0.0; prefs.remove('daily_goal'); } else { _dailyGoal = prefs.getDouble('daily_goal') ?? 0.0; } _bestDistance = 0.0; _bestSpeed = 0.0; _currentDistance = 0.0; _steps = 0; _totalTimeMinutes = 0; }); } } // Buscar corridas de hoje e calcular distância total Future _loadTodayDistance() async { try { final today = DateTime.now(); final startOfDay = DateTime(today.year, today.month, today.day); final endOfDay = startOfDay.add(const Duration(days: 1)); final runs = await SupabaseService.getUserRuns(limit: 100); double totalDistance = 0.0; for (final run in runs) { if (run['created_at'] != null) { final runDate = DateTime.parse(run['created_at']); if (runDate.isAfter(startOfDay) && runDate.isBefore(endOfDay)) { totalDistance += (run['distance'] ?? 0.0); } } } _currentDistance = totalDistance / 1000.0; // Converter para km } catch (e) { _currentDistance = 0.0; } } Future _saveGoal(double goal) async { final prefs = await SharedPreferences.getInstance(); final today = DateTime.now().toIso8601String().split('T')[0]; await prefs.setDouble('daily_goal', goal); await prefs.setString('last_goal_date', today); setState(() { _dailyGoal = goal; }); } void _showGoalDialog() { showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: AppColors.backgroundGrey, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), title: Text( AppStrings.defineDailyGoal, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), content: Column( mainAxisSize: MainAxisSize.min, children: [ ...[5, 10, 15, 20].map( (km) => ListTile( title: Text( "$km ${AppStrings.kmUnit}", style: const TextStyle(color: Colors.white), ), onTap: () { _saveGoal(km.toDouble()); Navigator.pop(context); }, ), ), const Divider(color: Colors.white10), ListTile( leading: const Icon( Icons.edit_note_rounded, color: AppColors.coral, ), title: Text( AppStrings.customGoal, style: const TextStyle( color: AppColors.coral, fontWeight: FontWeight.bold, ), ), onTap: () { Navigator.pop(context); _showCustomGoalDialog(); }, ), ], ), ), ); } void _showCustomGoalDialog() { final TextEditingController controller = TextEditingController(); showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: AppColors.backgroundGrey, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), title: Text( AppStrings.customGoalTitle, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), content: TextField( controller: controller, keyboardType: const TextInputType.numberWithOptions(decimal: true), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*')), ], style: const TextStyle(color: Colors.white), decoration: InputDecoration( hintText: "Ex: 12.5", hintStyle: const TextStyle(color: Colors.white24), suffixText: AppStrings.kmUnit, suffixStyle: const TextStyle(color: Colors.white54), enabledBorder: const UnderlineInputBorder( borderSide: BorderSide(color: Colors.white24), ), focusedBorder: const UnderlineInputBorder( borderSide: BorderSide(color: AppColors.coral), ), ), autofocus: true, ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text( AppStrings.btnCancel, style: const TextStyle(color: Colors.white54), ), ), ElevatedButton( onPressed: () { final value = double.tryParse(controller.text); if (value != null && value > 0) { _saveGoal(value); Navigator.pop(context); } }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.coral, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), ), child: Text( AppStrings.btnDefine, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ], ), ); } @override Widget build(BuildContext context) { return ValueListenableBuilder( valueListenable: AppStrings.languageNotifier, builder: (context, language, child) { final user = SupabaseService.currentUser; final userName = user?.userMetadata?['name'] ?? user?.email?.split('@')[0] ?? AppStrings.userPlaceholder; return Scaffold( backgroundColor: AppColors.background, body: Stack( children: [ Positioned.fill( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF2D2D31), AppColors.background], ), ), ), ), SafeArea( child: Column( children: [ Padding( padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 10, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( AppStrings.welcome.toUpperCase(), style: const TextStyle( color: Colors.white38, fontSize: 10, fontWeight: FontWeight.w900, letterSpacing: 2, ), ), Text( userName, style: const TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.w900, letterSpacing: -0.5, ), ), ], ), Row( children: [ _buildIconButton( Icons.bluetooth_audio_rounded, () => Navigator.push( context, MaterialPageRoute( builder: (context) => const BluetoothConnectionScreen(), ), ), ), const SizedBox(width: 12), _buildIconButton( Icons.settings_rounded, () => Navigator.push( context, MaterialPageRoute( builder: (context) => const SettingsScreen(), ), ), ), ], ), ], ), ), Expanded( child: SingleChildScrollView( physics: const BouncingScrollPhysics(), padding: const EdgeInsets.symmetric(horizontal: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 20), _buildMainTrackingCard(), const SizedBox(height: 30), Text( AppStrings.personalRecords, style: const TextStyle( color: Colors.white38, fontSize: 11, fontWeight: FontWeight.w900, letterSpacing: 1.5, ), ), const SizedBox(height: 15), Row( children: [ Expanded( child: _buildRecordCard( AppStrings.bestDistance, _bestDistance.toStringAsFixed(1), AppStrings.kmUnit, Icons.auto_graph_rounded, AppColors.coral, ), ), const SizedBox(width: 15), Expanded( child: _buildRecordCard( AppStrings.bestSpeed, _bestSpeed.toStringAsFixed(1), AppStrings.kmhUnit, Icons.speed_rounded, Colors.cyanAccent, ), ), ], ), const SizedBox(height: 25), Text( AppStrings.generalActivity, style: const TextStyle( color: Colors.white38, fontSize: 11, fontWeight: FontWeight.w900, letterSpacing: 1.5, ), ), const SizedBox(height: 15), _buildWideRecordCard( AppStrings.steps, _steps.toString(), AppStrings.stepsToday, Icons.directions_walk_rounded, AppColors.success, ), const SizedBox(height: 120), ], ), ), ), ], ), ), Positioned( bottom: 30, left: 50, right: 50, child: Container( height: 70, decoration: BoxDecoration( boxShadow: [ BoxShadow( color: AppColors.coral.withValues(alpha: 0.3), blurRadius: 25, spreadRadius: -5, ), ], ), child: ElevatedButton( onPressed: () => Navigator.push( context, MaterialPageRoute( builder: (context) => const GoogleMapScreen(), ), ), style: ElevatedButton.styleFrom( backgroundColor: AppColors.coral, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(25), ), elevation: 0, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.play_arrow_rounded, size: 30), const SizedBox(width: 10), Text( AppStrings.startTraining, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 1.5, ), ), ], ), ), ), ), ], ), ); }, ); } Widget _buildIconButton(IconData icon, VoidCallback onTap) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.05), borderRadius: BorderRadius.circular(15), border: Border.all(color: Colors.white10), ), child: Icon(icon, color: Colors.white, size: 22), ), ); } Widget _buildMainTrackingCard() { return Container( width: double.infinity, padding: const EdgeInsets.all(25), decoration: BoxDecoration( color: AppColors.backgroundGrey, borderRadius: BorderRadius.circular(45), border: Border.all(color: Colors.white10, width: 2), boxShadow: const [ BoxShadow( color: Colors.black26, blurRadius: 20, offset: Offset(0, 10), ), ], ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( AppStrings.dailyGoal, style: const TextStyle( color: Colors.white54, fontWeight: FontWeight.bold, letterSpacing: 1, ), ), if (_dailyGoal > 0) GestureDetector( onTap: _showGoalDialog, child: Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 4, ), decoration: BoxDecoration( color: AppColors.coral.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), ), child: Row( children: [ Text( "${(_progress * 100).toInt()}%", style: const TextStyle( color: AppColors.coral, fontWeight: FontWeight.w900, ), ), const SizedBox(width: 5), const Icon( Icons.edit_rounded, color: AppColors.coral, size: 14, ), ], ), ), ), ], ), const SizedBox(height: 20), Stack( alignment: Alignment.center, children: [ SizedBox( width: 180, height: 180, child: CircularProgressIndicator( value: _progress, strokeWidth: 15, backgroundColor: Colors.white.withValues(alpha: 0.05), valueColor: const AlwaysStoppedAnimation( AppColors.coral, ), strokeCap: StrokeCap.round, ), ), if (_dailyGoal == 0) GestureDetector( onTap: _showGoalDialog, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(15), decoration: BoxDecoration( color: AppColors.coral.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: const Icon( Icons.add_task_rounded, color: AppColors.coral, size: 40, ), ), const SizedBox(height: 10), Text( AppStrings.setGoal, style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w900, letterSpacing: 1, ), ), ], ), ) else Column( mainAxisSize: MainAxisSize.min, children: [ Text( AppStrings.distance, style: const TextStyle( color: Colors.white38, fontSize: 10, fontWeight: FontWeight.bold, letterSpacing: 2, ), ), Text( _currentDistance.toStringAsFixed(1), style: const TextStyle( color: Colors.white, fontSize: 48, fontWeight: FontWeight.w900, ), ), Text( "/ ${_dailyGoal.toStringAsFixed(1)} ${AppStrings.kmUnit}", style: const TextStyle( color: Colors.white54, fontSize: 14, fontWeight: FontWeight.bold, ), ), ], ), ], ), const SizedBox(height: 30), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildSimpleStat( AppStrings.steps, "${(_steps / 1000).toStringAsFixed(1)}k", ), const SizedBox(width: 40), _buildSimpleStat(AppStrings.time, "${_totalTimeMinutes}m"), ], ), ], ), ); } Widget _buildSimpleStat(String label, String value) { return Column( children: [ Text( value, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w900, fontSize: 16, ), ), Text( label, style: const TextStyle( color: Colors.white38, fontSize: 9, fontWeight: FontWeight.bold, ), ), ], ); } Widget _buildRecordCard( String title, String value, String unit, IconData icon, Color accentColor, ) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.backgroundGrey, borderRadius: BorderRadius.circular(30), border: Border.all(color: Colors.white10), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: accentColor.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon(icon, color: accentColor, size: 18), ), const SizedBox(height: 15), Row( crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ Text( value, style: const TextStyle( color: Colors.white, fontSize: 22, fontWeight: FontWeight.w900, ), ), const SizedBox(width: 4), Text( unit, style: const TextStyle( color: Colors.white38, fontSize: 10, fontWeight: FontWeight.bold, ), ), ], ), Text( title, style: const TextStyle( color: Colors.white54, fontSize: 9, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), ], ), ); } Widget _buildWideRecordCard( String title, String value, String unit, IconData icon, Color accentColor, ) { return Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.backgroundGrey, borderRadius: BorderRadius.circular(30), border: Border.all(color: Colors.white10), ), child: Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: accentColor.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon(icon, color: accentColor, size: 24), ), const SizedBox(width: 20), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ Text( value, style: const TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.w900, ), ), const SizedBox(width: 6), Text( unit, style: const TextStyle( color: Colors.white38, fontSize: 12, fontWeight: FontWeight.bold, ), ), ], ), Text( title, style: const TextStyle( color: Colors.white54, fontSize: 11, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), ], ), ], ), ); } }