507 lines
19 KiB
Dart
507 lines
19 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.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<LogadoScreen> createState() => _LogadoScreenState();
|
|
}
|
|
|
|
class _LogadoScreenState extends State<LogadoScreen> {
|
|
// Estado dinâmico do utilizador
|
|
double _dailyGoal = 0.0; // 0.0 significa que ainda não foi definida
|
|
double _currentDistance = 0.0;
|
|
double _bestDistance = 12.4; // Exemplo de recorde
|
|
double _bestSpeed = 16.8; // Exemplo de recorde
|
|
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();
|
|
}
|
|
|
|
Future<void> _loadUserData() async {
|
|
// No futuro, aqui buscaríamos os dados reais do Supabase ou Local Storage
|
|
setState(() {
|
|
// Simulação de dados carregados
|
|
_currentDistance = 0.0; // Começa o dia a zero
|
|
_steps = 0;
|
|
_totalTimeMinutes = 0;
|
|
});
|
|
}
|
|
|
|
void _showGoalDialog() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
backgroundColor: AppColors.backgroundGrey,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
|
|
title: const Text("Definir Meta Diária", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
...[5, 10, 15, 20].map((km) => ListTile(
|
|
title: Text("$km KM", style: const TextStyle(color: Colors.white)),
|
|
onTap: () {
|
|
setState(() {
|
|
_dailyGoal = km.toDouble();
|
|
});
|
|
Navigator.pop(context);
|
|
},
|
|
)),
|
|
const Divider(color: Colors.white10),
|
|
ListTile(
|
|
leading: const Icon(Icons.edit_note_rounded, color: AppColors.coral),
|
|
title: const Text("Personalizado", style: 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: const Text("Meta Personalizada", style: 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: "KM",
|
|
suffixStyle: const TextStyle(color: Colors.white54),
|
|
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white24)),
|
|
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: AppColors.coral)),
|
|
),
|
|
autofocus: true,
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text("CANCELAR", style: TextStyle(color: Colors.white54)),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
final value = double.tryParse(controller.text);
|
|
if (value != null && value > 0) {
|
|
setState(() {
|
|
_dailyGoal = value;
|
|
});
|
|
Navigator.pop(context);
|
|
}
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColors.coral,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
|
),
|
|
child: const Text("DEFINIR", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final user = SupabaseService.currentUser;
|
|
final userName = user?.userMetadata?['name'] ?? user?.email?.split('@')[0] ?? 'Corredor';
|
|
|
|
return Scaffold(
|
|
backgroundColor: AppColors.background,
|
|
body: Stack(
|
|
children: [
|
|
// Background Gradient
|
|
Positioned.fill(
|
|
child: Container(
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [Color(0xFF2D2D31), AppColors.background],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
SafeArea(
|
|
child: Column(
|
|
children: [
|
|
// Header Bar
|
|
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),
|
|
|
|
// Main Tracking Card (Meta Diária)
|
|
_buildMainTrackingCard(),
|
|
|
|
const SizedBox(height: 30),
|
|
|
|
// Personal Bests Section
|
|
const Text(
|
|
"RECORDS PESSOAIS",
|
|
style: 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),
|
|
|
|
// Steps Section (Atividade Geral)
|
|
const Text(
|
|
"ATIVIDADE GERAL",
|
|
style: TextStyle(
|
|
color: Colors.white38,
|
|
fontSize: 11,
|
|
fontWeight: FontWeight.w900,
|
|
letterSpacing: 1.5,
|
|
),
|
|
),
|
|
const SizedBox(height: 15),
|
|
_buildWideRecordCard(
|
|
AppStrings.steps,
|
|
_steps.toString(),
|
|
"passos hoje",
|
|
Icons.directions_walk_rounded,
|
|
AppColors.success,
|
|
),
|
|
|
|
const SizedBox(height: 120), // Espaço para o botão inferior
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Bottom Action Button
|
|
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: [
|
|
const Text(
|
|
AppStrings.dailyGoal,
|
|
style: TextStyle(color: Colors.white54, fontWeight: FontWeight.bold, letterSpacing: 1),
|
|
),
|
|
if (_dailyGoal > 0)
|
|
Text(
|
|
"${(_progress * 100).toInt()}%",
|
|
style: const TextStyle(color: AppColors.coral, fontWeight: FontWeight.w900),
|
|
),
|
|
],
|
|
),
|
|
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<Color>(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),
|
|
const Text(
|
|
"DEFINIR META",
|
|
style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w900, letterSpacing: 1),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
else
|
|
Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Text("DISTÂNCIA", style: 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("PASSOS", "${(_steps / 1000).toStringAsFixed(1)}k"),
|
|
const SizedBox(width: 40),
|
|
_buildSimpleStat("TEMPO", "${_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)),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|