login e register
This commit is contained in:
@@ -1,194 +1,146 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:playmaker/controllers/login_controller.dart';
|
||||
import 'package:playmaker/pages/RegisterPage.dart';
|
||||
import '../utils/size_extension.dart'; // 👇 O NOSSO SUPERPODER!
|
||||
|
||||
class BasketTrackHeader extends StatelessWidget {
|
||||
const BasketTrackHeader({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
|
||||
// TAMANHOS AUMENTADOS para tablets
|
||||
final logoSize = screenWidth > 600 ? 400.0 : 300.0; // ↑ Aumentado
|
||||
final titleFontSize = screenWidth > 600 ? 48.0 : 36.0; // ↑ Aumentado
|
||||
final subtitleFontSize = screenWidth > 600 ? 22.0 : 18.0; // ↑ Aumentado
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
width: logoSize,
|
||||
height: logoSize,
|
||||
child: Image.asset(
|
||||
'assets/playmaker-logo.png',
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
SizedBox(height: screenWidth > 600 ? 1.0 : 1.0),
|
||||
|
||||
Text(
|
||||
'BasketTrack',
|
||||
style: TextStyle(
|
||||
fontSize: titleFontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.grey[900],
|
||||
),
|
||||
),
|
||||
SizedBox(height: screenWidth > 600 ? 1.0 : 1.0),
|
||||
|
||||
Text(
|
||||
'Gere as tuas equipas e estatísticas',
|
||||
style: TextStyle(
|
||||
fontSize: subtitleFontSize,
|
||||
color: Colors.grey[600],
|
||||
fontWeight: FontWeight.w500, // ↑ Adicionado peso da fonte
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LoginFormFields extends StatelessWidget {
|
||||
final LoginController controller;
|
||||
|
||||
const LoginFormFields({super.key, required this.controller});
|
||||
class BasketTrackHeader extends StatelessWidget {
|
||||
const BasketTrackHeader({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final verticalPadding = screenWidth > 600 ? 22.0 : 16.0;
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 300 * context.sf, // Ajusta o tamanho da imagem suavemente
|
||||
height: 300 * context.sf,
|
||||
child: Image.asset(
|
||||
'assets/playmaker-logo.png',
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'BasketTrack',
|
||||
style: TextStyle(
|
||||
fontSize: 36 * context.sf,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.grey[900],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 6 * context.sf),
|
||||
Text(
|
||||
'Gere as tuas equipas e estatísticas',
|
||||
style: TextStyle(
|
||||
fontSize: 16 * context.sf,
|
||||
color: Colors.grey[600],
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LoginFormFields extends StatelessWidget {
|
||||
final LoginController controller;
|
||||
|
||||
const LoginFormFields({super.key, required this.controller});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: controller.emailController,
|
||||
style: TextStyle(fontSize: 15 * context.sf),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'E-mail',
|
||||
prefixIcon: const Icon(Icons.email_outlined),
|
||||
// O erro agora vem diretamente do controller
|
||||
labelStyle: TextStyle(fontSize: 15 * context.sf),
|
||||
prefixIcon: Icon(Icons.email_outlined, size: 22 * context.sf),
|
||||
errorText: controller.emailError,
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: verticalPadding, horizontal: 16),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12 * context.sf)),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 18 * context.sf, horizontal: 16 * context.sf),
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(height: 20 * context.sf),
|
||||
TextField(
|
||||
controller: controller.passwordController,
|
||||
obscureText: controller.obscurePassword,
|
||||
style: TextStyle(fontSize: 15 * context.sf),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Palavra-passe',
|
||||
prefixIcon: const Icon(Icons.lock_outlined),
|
||||
labelStyle: TextStyle(fontSize: 15 * context.sf),
|
||||
prefixIcon: Icon(Icons.lock_outlined, size: 22 * context.sf),
|
||||
errorText: controller.passwordError,
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(controller.obscurePassword
|
||||
? Icons.visibility_outlined
|
||||
: Icons.visibility_off_outlined),
|
||||
icon: Icon(
|
||||
controller.obscurePassword ? Icons.visibility_outlined : Icons.visibility_off_outlined,
|
||||
size: 22 * context.sf
|
||||
),
|
||||
onPressed: controller.togglePasswordVisibility,
|
||||
),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: verticalPadding, horizontal: 16),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12 * context.sf)),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 18 * context.sf, horizontal: 16 * context.sf),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
class LoginButton extends StatelessWidget {
|
||||
final LoginController controller;
|
||||
final VoidCallback onLoginSuccess;
|
||||
|
||||
const LoginButton({
|
||||
super.key,
|
||||
required this.controller,
|
||||
required this.onLoginSuccess,
|
||||
});
|
||||
class LoginButton extends StatelessWidget {
|
||||
final LoginController controller;
|
||||
final VoidCallback onLoginSuccess;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
|
||||
// BOTÕES MAIORES
|
||||
final buttonHeight = screenWidth > 600 ? 70.0 : 58.0; // ↑ Aumentado
|
||||
final fontSize = screenWidth > 600 ? 22.0 : 18.0; // ↑ Aumentado
|
||||
const LoginButton({super.key, required this.controller, required this.onLoginSuccess});
|
||||
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
height: buttonHeight,
|
||||
child: ElevatedButton(
|
||||
onPressed: controller.isLoading ? null : () async {
|
||||
final success = await controller.login();
|
||||
if (success) {
|
||||
onLoginSuccess();
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE74C3C),
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(14), // ↑ Bordas mais arredondadas
|
||||
),
|
||||
elevation: 3, // ↑ Sombra mais pronunciada
|
||||
),
|
||||
child: controller.isLoading
|
||||
? SizedBox(
|
||||
width: 28, // ↑ Aumentado
|
||||
height: 28, // ↑ Aumentado
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 3, // ↑ Aumentado
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'Entrar',
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.w700, //
|
||||
),
|
||||
),
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
height: 58 * context.sf,
|
||||
child: ElevatedButton(
|
||||
onPressed: controller.isLoading ? null : () async {
|
||||
final success = await controller.login();
|
||||
if (success) onLoginSuccess();
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE74C3C),
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14 * context.sf)),
|
||||
elevation: 3,
|
||||
),
|
||||
);
|
||||
}
|
||||
child: controller.isLoading
|
||||
? SizedBox(
|
||||
width: 28 * context.sf, height: 28 * context.sf,
|
||||
child: const CircularProgressIndicator(strokeWidth: 3, valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
|
||||
)
|
||||
: Text('Entrar', style: TextStyle(fontSize: 18 * context.sf, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CreateAccountButton extends StatelessWidget {
|
||||
const CreateAccountButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final buttonHeight = screenWidth > 600 ? 70.0 : 58.0;
|
||||
final fontSize = screenWidth > 600 ? 22.0 : 18.0;
|
||||
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
height: buttonHeight,
|
||||
height: 58 * context.sf,
|
||||
child: OutlinedButton(
|
||||
onPressed: () {
|
||||
// Navega para a página de registo que criaste
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const RegisterPage()),
|
||||
);
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) => const RegisterPage()));
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: const Color(0xFFE74C3C),
|
||||
side: const BorderSide(color: Color(0xFFE74C3C), width: 2),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Criar Conta',
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
side: BorderSide(color: const Color(0xFFE74C3C), width: 2 * context.sf),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14 * context.sf)),
|
||||
),
|
||||
child: Text('Criar Conta', style: TextStyle(fontSize: 18 * context.sf, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user