Settings finalizadas
This commit is contained in:
@@ -1,19 +1,31 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
enum AppLanguage { pt, en, es }
|
enum AppLanguage { pt, en, es }
|
||||||
|
|
||||||
class AppStrings {
|
class AppStrings {
|
||||||
static AppLanguage _currentLanguage = AppLanguage.pt;
|
static final ValueNotifier<AppLanguage> languageNotifier = ValueNotifier(AppLanguage.pt);
|
||||||
|
|
||||||
|
static AppLanguage get currentLanguage => languageNotifier.value;
|
||||||
|
|
||||||
static void setLanguage(String language) {
|
static void setLanguage(String language) {
|
||||||
if (language == 'English') {
|
if (language == 'English') {
|
||||||
_currentLanguage = AppLanguage.en;
|
languageNotifier.value = AppLanguage.en;
|
||||||
} else if (language == 'Español') {
|
} else if (language == 'Español') {
|
||||||
_currentLanguage = AppLanguage.es;
|
languageNotifier.value = AppLanguage.es;
|
||||||
} else {
|
} else {
|
||||||
_currentLanguage = AppLanguage.pt;
|
languageNotifier.value = AppLanguage.pt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String get _lang => _currentLanguage.name;
|
static String get currentLanguageName {
|
||||||
|
switch (languageNotifier.value) {
|
||||||
|
case AppLanguage.en: return 'English';
|
||||||
|
case AppLanguage.es: return 'Español';
|
||||||
|
case AppLanguage.pt: return 'Português';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String get _lang => languageNotifier.value.name;
|
||||||
|
|
||||||
static String _get(Map<String, String> values) => values[_lang] ?? values['pt']!;
|
static String _get(Map<String, String> values) => values[_lang] ?? values['pt']!;
|
||||||
|
|
||||||
@@ -162,6 +174,7 @@ class AppStrings {
|
|||||||
static String get btnOk => _get({'pt': "OK", 'en': "OK", 'es': "OK"});
|
static String get btnOk => _get({'pt': "OK", 'en': "OK", 'es': "OK"});
|
||||||
static String get btnCancel => _get({'pt': "Cancelar", 'en': "Cancel", 'es': "Cancelar"});
|
static String get btnCancel => _get({'pt': "Cancelar", 'en': "Cancel", 'es': "Cancelar"});
|
||||||
static String get btnDefine => _get({'pt': "DEFINIR", 'en': "DEFINE", 'es': "DEFINIR"});
|
static String get btnDefine => _get({'pt': "DEFINIR", 'en': "DEFINE", 'es': "DEFINIR"});
|
||||||
|
static String get profileUpdated => _get({'pt': "Perfil atualizado!", 'en': "Profile updated!", 'es': "¡Perfil actualizado!"});
|
||||||
|
|
||||||
// Logado Screen
|
// Logado Screen
|
||||||
static String get defineDailyGoal => _get({'pt': "Definir Meta Diária", 'en': "Set Daily Goal", 'es': "Definir Meta Diaria"});
|
static String get defineDailyGoal => _get({'pt': "Definir Meta Diária", 'en': "Set Daily Goal", 'es': "Definir Meta Diaria"});
|
||||||
|
|||||||
@@ -15,33 +15,22 @@ void main() async {
|
|||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const MyApp({super.key});
|
||||||
|
|
||||||
// This widget is the root of your application.
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return ValueListenableBuilder<AppLanguage>(
|
||||||
title: AppStrings.appTitle,
|
valueListenable: AppStrings.languageNotifier,
|
||||||
debugShowCheckedModeBanner: false,
|
builder: (context, language, child) {
|
||||||
theme: ThemeData(
|
return MaterialApp(
|
||||||
// This is the theme of your application.
|
title: AppStrings.appTitle,
|
||||||
//
|
debugShowCheckedModeBanner: false,
|
||||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
theme: ThemeData(
|
||||||
// the application has a purple toolbar. Then, without quitting the app,
|
colorScheme: ColorScheme.fromSeed(
|
||||||
// try changing the seedColor in the colorScheme below to Colors.green
|
seedColor: Colors.white.withValues(alpha: 0.1),
|
||||||
// and then invoke "hot reload" (save your changes or press the "hot
|
),
|
||||||
// reload" button in a Flutter-supported IDE, or press "r" if you used
|
),
|
||||||
// the command line to start the app).
|
home: const InicialScreen(),
|
||||||
//
|
);
|
||||||
// Notice that the counter didn't reset back to zero; the application
|
},
|
||||||
// state is not lost during the reload. To reset the state, use hot
|
|
||||||
// restart instead.
|
|
||||||
//
|
|
||||||
// This works for code too, not just values: Most code changes can be
|
|
||||||
// tested with just a hot reload.
|
|
||||||
colorScheme: ColorScheme.fromSeed(
|
|
||||||
seedColor: Colors.white.withValues(alpha: 0.1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
home: const InicialScreen(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import '../constants/app_colors.dart';
|
import '../constants/app_colors.dart';
|
||||||
import '../constants/app_strings.dart';
|
import '../constants/app_strings.dart';
|
||||||
import '../services/supabase_service.dart';
|
import '../services/supabase_service.dart';
|
||||||
@@ -16,10 +17,10 @@ class LogadoScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _LogadoScreenState extends State<LogadoScreen> {
|
class _LogadoScreenState extends State<LogadoScreen> {
|
||||||
// Estado dinâmico do utilizador
|
// Estado dinâmico do utilizador
|
||||||
double _dailyGoal = 0.0; // 0.0 significa que ainda não foi definida
|
double _dailyGoal = 0.0;
|
||||||
double _currentDistance = 0.0;
|
double _currentDistance = 0.0;
|
||||||
double _bestDistance = 12.4; // Exemplo de recorde
|
double _bestDistance = 12.4;
|
||||||
double _bestSpeed = 16.8; // Exemplo de recorde
|
double _bestSpeed = 16.8;
|
||||||
int _steps = 0;
|
int _steps = 0;
|
||||||
int _totalTimeMinutes = 0;
|
int _totalTimeMinutes = 0;
|
||||||
|
|
||||||
@@ -32,15 +33,38 @@ class _LogadoScreenState extends State<LogadoScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadUserData() async {
|
Future<void> _loadUserData() async {
|
||||||
// No futuro, aqui buscaríamos os dados reais do Supabase ou Local Storage
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final lastGoalDate = prefs.getString('last_goal_date');
|
||||||
|
final today = DateTime.now().toIso8601String().split('T')[0];
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
// Simulação de dados carregados
|
// Reset meta se o dia mudou
|
||||||
_currentDistance = 0.0; // Começa o dia a zero
|
if (lastGoalDate != today) {
|
||||||
|
_dailyGoal = 0.0;
|
||||||
|
prefs.remove('daily_goal');
|
||||||
|
} else {
|
||||||
|
_dailyGoal = prefs.getDouble('daily_goal') ?? 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No futuro, estes viriam do Supabase ou histórico local
|
||||||
|
_currentDistance = 0.0;
|
||||||
_steps = 0;
|
_steps = 0;
|
||||||
_totalTimeMinutes = 0;
|
_totalTimeMinutes = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _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() {
|
void _showGoalDialog() {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -54,9 +78,7 @@ class _LogadoScreenState extends State<LogadoScreen> {
|
|||||||
...[5, 10, 15, 20].map((km) => ListTile(
|
...[5, 10, 15, 20].map((km) => ListTile(
|
||||||
title: Text("$km ${AppStrings.kmUnit}", style: const TextStyle(color: Colors.white)),
|
title: Text("$km ${AppStrings.kmUnit}", style: const TextStyle(color: Colors.white)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
_saveGoal(km.toDouble());
|
||||||
_dailyGoal = km.toDouble();
|
|
||||||
});
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
@@ -107,9 +129,7 @@ class _LogadoScreenState extends State<LogadoScreen> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
final value = double.tryParse(controller.text);
|
final value = double.tryParse(controller.text);
|
||||||
if (value != null && value > 0) {
|
if (value != null && value > 0) {
|
||||||
setState(() {
|
_saveGoal(value);
|
||||||
_dailyGoal = value;
|
|
||||||
});
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -126,194 +146,187 @@ class _LogadoScreenState extends State<LogadoScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final user = SupabaseService.currentUser;
|
return ValueListenableBuilder<AppLanguage>(
|
||||||
final userName = user?.userMetadata?['name'] ?? user?.email?.split('@')[0] ?? AppStrings.userPlaceholder;
|
valueListenable: AppStrings.languageNotifier,
|
||||||
|
builder: (context, language, child) {
|
||||||
|
final user = SupabaseService.currentUser;
|
||||||
|
final userName = user?.userMetadata?['name'] ?? user?.email?.split('@')[0] ?? AppStrings.userPlaceholder;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColors.background,
|
backgroundColor: AppColors.background,
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
// Background Gradient
|
Positioned.fill(
|
||||||
Positioned.fill(
|
child: Container(
|
||||||
child: Container(
|
decoration: const BoxDecoration(
|
||||||
decoration: const BoxDecoration(
|
gradient: LinearGradient(
|
||||||
gradient: LinearGradient(
|
begin: Alignment.topCenter,
|
||||||
begin: Alignment.topCenter,
|
end: Alignment.bottomCenter,
|
||||||
end: Alignment.bottomCenter,
|
colors: [Color(0xFF2D2D31), AppColors.background],
|
||||||
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
|
|
||||||
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),
|
|
||||||
|
|
||||||
// Steps Section (Atividade Geral)
|
|
||||||
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), // 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())),
|
SafeArea(
|
||||||
style: ElevatedButton.styleFrom(
|
child: Column(
|
||||||
backgroundColor: AppColors.coral,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
|
|
||||||
elevation: 0,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.play_arrow_rounded, size: 30),
|
Padding(
|
||||||
const SizedBox(width: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||||
Text(
|
child: Row(
|
||||||
AppStrings.startTraining,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 1.5),
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,9 +365,25 @@ class _LogadoScreenState extends State<LogadoScreen> {
|
|||||||
style: const TextStyle(color: Colors.white54, fontWeight: FontWeight.bold, letterSpacing: 1),
|
style: const TextStyle(color: Colors.white54, fontWeight: FontWeight.bold, letterSpacing: 1),
|
||||||
),
|
),
|
||||||
if (_dailyGoal > 0)
|
if (_dailyGoal > 0)
|
||||||
Text(
|
GestureDetector(
|
||||||
"${(_progress * 100).toInt()}%",
|
onTap: _showGoalDialog,
|
||||||
style: const TextStyle(color: AppColors.coral, fontWeight: FontWeight.w900),
|
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),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ class SettingsScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SettingsScreenState extends State<SettingsScreen> {
|
class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
bool _isNightMode = true;
|
late String _selectedLanguage;
|
||||||
bool _notificationsEnabled = true;
|
|
||||||
String _selectedLanguage = 'Português';
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedLanguage = AppStrings.currentLanguageName;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -93,12 +97,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.edit, color: AppColors.buttonColor),
|
icon: const Icon(Icons.edit, color: AppColors.buttonColor),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
_showEditProfileDialog(context, userName, userEmail);
|
||||||
SnackBar(
|
|
||||||
content: Text(AppStrings.editProfile),
|
|
||||||
backgroundColor: AppColors.buttonColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -115,28 +114,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
_buildSettingsItem(
|
|
||||||
icon: Icons.schedule,
|
|
||||||
title: AppStrings.adjustDateTime,
|
|
||||||
onTap: () {
|
|
||||||
_showDatePicker(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildDivider(),
|
|
||||||
_buildSettingsItem(
|
|
||||||
icon: Icons.dark_mode,
|
|
||||||
title: AppStrings.nightMode,
|
|
||||||
trailing: Switch(
|
|
||||||
value: _isNightMode,
|
|
||||||
activeThumbColor: AppColors.buttonColor,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
_isNightMode = value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_buildDivider(),
|
|
||||||
_buildSettingsItem(
|
_buildSettingsItem(
|
||||||
icon: Icons.language,
|
icon: Icons.language,
|
||||||
title: AppStrings.language,
|
title: AppStrings.language,
|
||||||
@@ -152,59 +129,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
_buildDivider(),
|
_buildDivider(),
|
||||||
_buildSettingsItem(
|
|
||||||
icon: Icons.accessibility,
|
|
||||||
title: AppStrings.accessibility,
|
|
||||||
onTap: () {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(AppStrings.accessibility),
|
|
||||||
backgroundColor: AppColors.buttonColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildDivider(),
|
|
||||||
_buildSettingsItem(
|
|
||||||
icon: Icons.notifications,
|
|
||||||
title: AppStrings.notifications,
|
|
||||||
trailing: Switch(
|
|
||||||
value: _notificationsEnabled,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
_notificationsEnabled = value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
activeThumbColor: AppColors.buttonColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_buildDivider(),
|
|
||||||
_buildSettingsItem(
|
|
||||||
icon: Icons.privacy_tip,
|
|
||||||
title: AppStrings.privacySecurity,
|
|
||||||
onTap: () {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(AppStrings.privacySecurity),
|
|
||||||
backgroundColor: AppColors.buttonColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildDivider(),
|
|
||||||
_buildSettingsItem(
|
|
||||||
icon: Icons.description,
|
|
||||||
title: AppStrings.termsOfUse,
|
|
||||||
onTap: () {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(AppStrings.termsOfUse),
|
|
||||||
backgroundColor: AppColors.buttonColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildDivider(),
|
|
||||||
_buildSettingsItem(
|
_buildSettingsItem(
|
||||||
icon: Icons.info,
|
icon: Icons.info,
|
||||||
title: AppStrings.about,
|
title: AppStrings.about,
|
||||||
@@ -278,39 +202,42 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDatePicker(BuildContext context) {
|
void _showEditProfileDialog(BuildContext context, String currentName, String currentEmail) {
|
||||||
showDatePicker(
|
final nameController = TextEditingController(text: currentName);
|
||||||
context: context,
|
final emailController = TextEditingController(text: currentEmail);
|
||||||
initialDate: DateTime.now(),
|
|
||||||
firstDate: DateTime(2020),
|
|
||||||
lastDate: DateTime(2025),
|
|
||||||
).then((date) {
|
|
||||||
if (date != null && mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text('${AppStrings.dateSelected}: ${date.toString().split(' ')[0]}'),
|
|
||||||
backgroundColor: AppColors.buttonColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showLanguageSelector(BuildContext context) {
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
backgroundColor: AppColors.backgroundGrey,
|
backgroundColor: AppColors.backgroundGrey,
|
||||||
title: Text(
|
title: Text(
|
||||||
AppStrings.selectLanguage,
|
AppStrings.editProfile,
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
_buildLanguageOption('Português'),
|
TextField(
|
||||||
_buildLanguageOption('English'),
|
controller: nameController,
|
||||||
_buildLanguageOption('Español'),
|
style: const TextStyle(color: Colors.white),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: AppStrings.labelName,
|
||||||
|
labelStyle: const TextStyle(color: Colors.white70),
|
||||||
|
enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Colors.white24)),
|
||||||
|
focusedBorder: const UnderlineInputBorder(borderSide: BorderSide(color: AppColors.buttonColor)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextField(
|
||||||
|
controller: emailController,
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: AppStrings.labelEmail,
|
||||||
|
labelStyle: const TextStyle(color: Colors.white70),
|
||||||
|
enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Colors.white24)),
|
||||||
|
focusedBorder: const UnderlineInputBorder(borderSide: BorderSide(color: AppColors.buttonColor)),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -318,15 +245,74 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
AppStrings.btnCancel,
|
AppStrings.btnCancel,
|
||||||
style: const TextStyle(color: AppColors.buttonColor),
|
style: const TextStyle(color: Colors.white54),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
await SupabaseService.updateProfile(
|
||||||
|
name: nameController.text.trim(),
|
||||||
|
email: emailController.text.trim(),
|
||||||
|
);
|
||||||
|
if (context.mounted) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
setState(() {});
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text('Perfil atualizado!'), backgroundColor: Colors.green),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text(e.toString()), backgroundColor: Colors.red),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(backgroundColor: AppColors.buttonColor),
|
||||||
|
child: Text(AppStrings.btnDefine),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLanguageOption(String language) {
|
void _showLanguageSelector(BuildContext context) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => StatefulBuilder(
|
||||||
|
builder: (context, setDialogState) {
|
||||||
|
return AlertDialog(
|
||||||
|
backgroundColor: AppColors.backgroundGrey,
|
||||||
|
title: Text(
|
||||||
|
AppStrings.selectLanguage,
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
_buildLanguageOption(context, setDialogState, 'Português'),
|
||||||
|
_buildLanguageOption(context, setDialogState, 'English'),
|
||||||
|
_buildLanguageOption(context, setDialogState, 'Español'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text(
|
||||||
|
AppStrings.btnCancel,
|
||||||
|
style: const TextStyle(color: AppColors.buttonColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildLanguageOption(BuildContext context, StateSetter setDialogState, String language) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(language, style: const TextStyle(color: Colors.white)),
|
title: Text(language, style: const TextStyle(color: Colors.white)),
|
||||||
trailing: Radio<String>(
|
trailing: Radio<String>(
|
||||||
@@ -334,28 +320,26 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
groupValue: _selectedLanguage,
|
groupValue: _selectedLanguage,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
setState(() {
|
_updateLanguage(value);
|
||||||
_selectedLanguage = value;
|
|
||||||
AppStrings.setLanguage(value);
|
|
||||||
});
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
// Force rebuild of current screen to apply changes
|
|
||||||
setState(() {});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fillColor: WidgetStateProperty.all(AppColors.buttonColor),
|
fillColor: WidgetStateProperty.all(AppColors.buttonColor),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
_updateLanguage(language);
|
||||||
_selectedLanguage = language;
|
|
||||||
AppStrings.setLanguage(language);
|
|
||||||
});
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
setState(() {});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _updateLanguage(String language) {
|
||||||
|
setState(() {
|
||||||
|
_selectedLanguage = language;
|
||||||
|
AppStrings.setLanguage(language);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _showAboutDialog(BuildContext context) {
|
void _showAboutDialog(BuildContext context) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
|||||||
@@ -2,27 +2,19 @@ import 'package:supabase_flutter/supabase_flutter.dart';
|
|||||||
import '../constants/app_constants.dart';
|
import '../constants/app_constants.dart';
|
||||||
|
|
||||||
class SupabaseService {
|
class SupabaseService {
|
||||||
static final SupabaseClient _supabase = Supabase.instance.client;
|
static SupabaseClient get _supabase => Supabase.instance.client;
|
||||||
|
|
||||||
// Initialize Supabase
|
// Initialize Supabase
|
||||||
static Future<void> initialize() async {
|
static Future<void> initialize() async {
|
||||||
try {
|
try {
|
||||||
print('DEBUG: Inicializando Supabase...');
|
print('DEBUG: Inicializando Supabase...');
|
||||||
print('DEBUG: URL: ${AppConstants.supabaseUrl}');
|
|
||||||
print(
|
|
||||||
'DEBUG: AnonKey: ${AppConstants.supabaseAnonKey.substring(0, 10)}...',
|
|
||||||
);
|
|
||||||
|
|
||||||
await Supabase.initialize(
|
await Supabase.initialize(
|
||||||
url: AppConstants.supabaseUrl,
|
url: AppConstants.supabaseUrl,
|
||||||
anonKey: AppConstants.supabaseAnonKey,
|
anonKey: AppConstants.supabaseAnonKey,
|
||||||
);
|
);
|
||||||
|
|
||||||
print('DEBUG: Supabase inicializado com sucesso!');
|
print('DEBUG: Supabase inicializado com sucesso!');
|
||||||
|
|
||||||
// Test connection
|
|
||||||
final currentUser = _supabase.auth.currentUser;
|
|
||||||
print('DEBUG: Usuário atual: ${currentUser?.email ?? 'null'}');
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Erro ao inicializar Supabase: $e');
|
print('DEBUG: Erro ao inicializar Supabase: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
@@ -39,26 +31,18 @@ class SupabaseService {
|
|||||||
required String name,
|
required String name,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
print('DEBUG: Criando conta - Email: $email, Name: $name');
|
|
||||||
|
|
||||||
final response = await _supabase.auth.signUp(
|
final response = await _supabase.auth.signUp(
|
||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
data: {'name': name},
|
data: {'name': name},
|
||||||
);
|
);
|
||||||
|
|
||||||
print('DEBUG: Conta criada! User ID: ${response.user?.id}');
|
|
||||||
|
|
||||||
// Check if user was created successfully
|
|
||||||
if (response.user != null) {
|
if (response.user != null) {
|
||||||
print('DEBUG: Usuário criado com sucesso!');
|
|
||||||
return response;
|
return response;
|
||||||
} else {
|
} else {
|
||||||
print('DEBUG: Falha ao criar usuário - response.user é null');
|
throw Exception('Falha ao criar usuário.');
|
||||||
throw Exception('Falha ao criar usuário. Tente novamente.');
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Erro no signUp: $e');
|
|
||||||
throw Exception('Erro ao criar conta: $e');
|
throw Exception('Erro ao criar conta: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,17 +53,11 @@ class SupabaseService {
|
|||||||
required String password,
|
required String password,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
print('DEBUG: Fazendo login - Email: $email');
|
return await _supabase.auth.signInWithPassword(
|
||||||
|
|
||||||
final response = await _supabase.auth.signInWithPassword(
|
|
||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
|
|
||||||
print('DEBUG: Login realizado! User ID: ${response.user?.id}');
|
|
||||||
return response;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Erro no signIn: $e');
|
|
||||||
throw Exception('Erro ao fazer login: $e');
|
throw Exception('Erro ao fazer login: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,9 +66,7 @@ class SupabaseService {
|
|||||||
static Future<void> signOut() async {
|
static Future<void> signOut() async {
|
||||||
try {
|
try {
|
||||||
await _supabase.auth.signOut();
|
await _supabase.auth.signOut();
|
||||||
print('DEBUG: Logout realizado');
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Erro no signOut: $e');
|
|
||||||
throw Exception('Erro ao sair: $e');
|
throw Exception('Erro ao sair: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,27 +75,34 @@ class SupabaseService {
|
|||||||
static Future<void> resetPassword(String email) async {
|
static Future<void> resetPassword(String email) async {
|
||||||
try {
|
try {
|
||||||
await _supabase.auth.resetPasswordForEmail(email);
|
await _supabase.auth.resetPasswordForEmail(email);
|
||||||
print('DEBUG: Email de reset enviado para: $email');
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Erro no resetPassword: $e');
|
|
||||||
throw Exception('Erro ao redefinir senha: $e');
|
throw Exception('Erro ao redefinir senha: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update user profile
|
||||||
|
static Future<void> updateProfile({String? name, String? email}) async {
|
||||||
|
try {
|
||||||
|
final updates = <String, dynamic>{};
|
||||||
|
if (name != null) updates['name'] = name;
|
||||||
|
|
||||||
|
final userAttributes = UserAttributes(
|
||||||
|
data: updates.isNotEmpty ? updates : null,
|
||||||
|
email: email,
|
||||||
|
);
|
||||||
|
|
||||||
|
await _supabase.auth.updateUser(userAttributes);
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Erro ao atualizar perfil: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test connection to Supabase
|
// Test connection to Supabase
|
||||||
static Future<bool> testConnection() async {
|
static Future<bool> testConnection() async {
|
||||||
try {
|
try {
|
||||||
print('DEBUG: Testando conexão com Supabase...');
|
|
||||||
|
|
||||||
// Test with auth service instead of database
|
|
||||||
final session = _supabase.auth.currentSession;
|
final session = _supabase.auth.currentSession;
|
||||||
print('DEBUG: Sessão atual: ${session != null ? 'ativa' : 'null'}');
|
|
||||||
|
|
||||||
// Try to get auth settings (this should work even without tables)
|
|
||||||
print('DEBUG: Conexão básica funcionando!');
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Erro na conexão: $e');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
|
|
||||||
// Show success message above the sheet
|
// Show success message above the sheet
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
SnackBar(
|
||||||
content: Text(AppStrings.loginSuccess),
|
content: Text(AppStrings.loginSuccess),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
),
|
||||||
@@ -66,7 +66,7 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
final email = _emailController.text.trim();
|
final email = _emailController.text.trim();
|
||||||
if (email.isEmpty) {
|
if (email.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
SnackBar(
|
||||||
content: Text(AppStrings.validatorEmailEmpty),
|
content: Text(AppStrings.validatorEmailEmpty),
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.orange,
|
||||||
),
|
),
|
||||||
@@ -82,7 +82,7 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
|
|
||||||
// Show success message above the sheet
|
// Show success message above the sheet
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
SnackBar(
|
||||||
content: Text(AppStrings.resetPasswordEmailSent),
|
content: Text(AppStrings.resetPasswordEmailSent),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
),
|
||||||
@@ -115,7 +115,7 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
minChildSize: 0.4, // 40% minimum
|
minChildSize: 0.4, // 40% minimum
|
||||||
maxChildSize: 0.9, // 90% maximum
|
maxChildSize: 0.9, // 90% maximum
|
||||||
snap: true, // Enable snap points
|
snap: true, // Enable snap points
|
||||||
snapSizes: [0.6, 0.9], // Snap to 60% or 90%
|
snapSizes: const [0.6, 0.9], // Snap to 60% or 90%
|
||||||
builder: (context, scrollController) {
|
builder: (context, scrollController) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -151,9 +151,9 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
const Text(
|
Text(
|
||||||
AppStrings.loginTitle,
|
AppStrings.loginTitle,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@@ -162,9 +162,9 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
|
|
||||||
// Email field
|
// Email field
|
||||||
const Text(
|
Text(
|
||||||
AppStrings.labelEmail,
|
AppStrings.labelEmail,
|
||||||
style: TextStyle(fontSize: 16, color: Colors.white70),
|
style: const TextStyle(fontSize: 16, color: Colors.white70),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Form(
|
Form(
|
||||||
@@ -196,9 +196,9 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
// Password field
|
// Password field
|
||||||
const Text(
|
Text(
|
||||||
AppStrings.labelPassword,
|
AppStrings.labelPassword,
|
||||||
style: TextStyle(fontSize: 16, color: Colors.white70),
|
style: const TextStyle(fontSize: 16, color: Colors.white70),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
@@ -245,9 +245,9 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
? const CircularProgressIndicator(
|
? const CircularProgressIndicator(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
)
|
)
|
||||||
: const Text(
|
: Text(
|
||||||
AppStrings.btnLogin,
|
AppStrings.btnLogin,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
@@ -260,9 +260,9 @@ class _EntrarSheetState extends State<EntrarSheet> {
|
|||||||
Center(
|
Center(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: _handlePasswordReset,
|
onPressed: _handlePasswordReset,
|
||||||
child: const Text(
|
child: Text(
|
||||||
AppStrings.forgotPassword,
|
AppStrings.forgotPassword,
|
||||||
style: TextStyle(color: Colors.white70, fontSize: 16),
|
style: const TextStyle(color: Colors.white70, fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@@ -85,10 +85,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.1"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -548,18 +548,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.19"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.1"
|
version: "0.13.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -945,10 +945,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.7"
|
version: "0.7.10"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user