CKT String|Colors
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'colors/app_colors.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
@@ -8,15 +9,16 @@ import 'auth_gate.dart' show pendingPrivacyUserId, pendingTermsUserId;
|
||||
import 'main.dart' show supabase;
|
||||
import 'privacy_gate_prefs.dart';
|
||||
import 'terms_gate_prefs.dart';
|
||||
import 'widgets/app_gradients.dart';
|
||||
import 'colors/app_gradients.dart';
|
||||
import 'strings/auth_strings.dart';
|
||||
import 'widgets/entrance.dart';
|
||||
import 'widgets/liquid_waves_background.dart';
|
||||
import 'widgets/name_input_formatter.dart';
|
||||
import 'widgets/pill_snackbar.dart';
|
||||
import 'widgets/tap_bounce.dart';
|
||||
|
||||
const Color _teal = Color(0xFF2F9E94);
|
||||
const Color _pink = Color(0xFFFF55A7);
|
||||
const Color _teal = AppColors.teal;
|
||||
const Color _pink = AppColors.pink;
|
||||
|
||||
/// Nomes só podem ter letras (incluindo acentuadas) e espaços — sem números.
|
||||
final RegExp _namePattern = RegExp(r"^[a-zA-ZÀ-ÖØ-öø-ÿ' -]+$");
|
||||
@@ -113,7 +115,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
|
||||
final user = response.user;
|
||||
if (user == null) {
|
||||
throw StateError('Utilizador não encontrado após criar a conta.');
|
||||
throw StateError(AuthStrings.userNotFoundAfterSignUp);
|
||||
}
|
||||
|
||||
// Antes de persistir o perfil (o que já faz o AuthGate considerar a
|
||||
@@ -137,7 +139,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
if (!mounted) return;
|
||||
showPillSnackBar(
|
||||
context,
|
||||
'Esta conta já não existe. Verifique o email ou crie uma nova conta.',
|
||||
AuthStrings.accountNoLongerExists,
|
||||
);
|
||||
} on AuthException catch (e) {
|
||||
if (!mounted) return;
|
||||
@@ -146,11 +148,11 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
if (!mounted) return;
|
||||
showPillSnackBar(
|
||||
context,
|
||||
'Tempo esgotado. Verifique a sua ligação e tente novamente.',
|
||||
AuthStrings.timeoutError,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
showPillSnackBar(context, 'Erro: $e');
|
||||
showPillSnackBar(context, AuthStrings.genericError(e));
|
||||
} finally {
|
||||
if (mounted) setState(() => _loading = false);
|
||||
}
|
||||
@@ -159,14 +161,14 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
String _friendlyAuthError(AuthException e) {
|
||||
switch (e.code) {
|
||||
case 'invalid_credentials':
|
||||
return 'Email ou palavra-passe incorretos.';
|
||||
return AuthStrings.invalidCredentials;
|
||||
case 'user_not_found':
|
||||
return 'Utilizador não encontrado.';
|
||||
return AuthStrings.userNotFound;
|
||||
case 'email_exists':
|
||||
case 'user_already_exists':
|
||||
return 'Este email já está em uso.';
|
||||
return AuthStrings.emailAlreadyInUse;
|
||||
case 'weak_password':
|
||||
return 'Palavra-passe fraca. Utilize pelo menos 6 caracteres.';
|
||||
return AuthStrings.weakPassword;
|
||||
default:
|
||||
return e.message;
|
||||
}
|
||||
@@ -178,7 +180,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
body: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(child: Container(color: const Color(0xFFFAFAF7))),
|
||||
Positioned.fill(child: Container(color: AppColors.background)),
|
||||
const LiquidWavesBackground(),
|
||||
SafeArea(
|
||||
child: LayoutBuilder(
|
||||
@@ -195,7 +197,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
children: [
|
||||
const FadeSlideIn(
|
||||
child: Text(
|
||||
'Check-Teeth Kids',
|
||||
AuthStrings.appTitle,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 26,
|
||||
@@ -210,7 +212,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
FadeSlideIn(
|
||||
delay: const Duration(milliseconds: 80),
|
||||
child: Text(
|
||||
'Deteção e Prevenção da Má Oclusão Infantil',
|
||||
AuthStrings.appSubtitle,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 13.5,
|
||||
@@ -279,14 +281,14 @@ class _AuthTabSwitch extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: _AuthTab(
|
||||
label: 'Entrar',
|
||||
label: AuthStrings.login,
|
||||
selected: isLogin,
|
||||
onTap: () => onChanged(true),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _AuthTab(
|
||||
label: 'Criar Conta',
|
||||
label: AuthStrings.createAccount,
|
||||
selected: !isLogin,
|
||||
onTap: () => onChanged(false),
|
||||
),
|
||||
@@ -376,17 +378,17 @@ class _AuthForm extends StatelessWidget {
|
||||
children: [
|
||||
_AuthTextField(
|
||||
controller: nameController,
|
||||
hintText: 'Introduza o seu nome',
|
||||
hintText: AuthStrings.nameHint,
|
||||
icon: Icons.person_outline_rounded,
|
||||
textInputAction: TextInputAction.next,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
inputFormatters: [CapitalizeFirstLetterFormatter()],
|
||||
validator: (v) {
|
||||
final value = (v ?? '').trim();
|
||||
if (value.isEmpty) return 'Indique o seu nome';
|
||||
if (value.length < 2) return 'Nome muito curto';
|
||||
if (value.isEmpty) return AuthStrings.nameRequired;
|
||||
if (value.length < 2) return AuthStrings.nameTooShort;
|
||||
if (!_namePattern.hasMatch(value)) {
|
||||
return 'O nome não pode conter números';
|
||||
return AuthStrings.nameNoNumbers;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -398,28 +400,28 @@ class _AuthForm extends StatelessWidget {
|
||||
),
|
||||
_AuthTextField(
|
||||
controller: emailController,
|
||||
hintText: 'Introduza o seu email',
|
||||
hintText: AuthStrings.emailHint,
|
||||
icon: Icons.mail_outline_rounded,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (v) {
|
||||
final value = (v ?? '').trim();
|
||||
if (value.isEmpty) return 'Indique o seu email';
|
||||
if (!value.contains('@')) return 'Email inválido';
|
||||
if (value.isEmpty) return AuthStrings.emailRequired;
|
||||
if (!value.contains('@')) return AuthStrings.emailInvalid;
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_AuthTextField(
|
||||
controller: passwordController,
|
||||
hintText: 'Introduza a sua palavra-passe',
|
||||
hintText: AuthStrings.passwordHint,
|
||||
icon: Icons.lock_outline_rounded,
|
||||
obscureText: true,
|
||||
textInputAction: TextInputAction.done,
|
||||
validator: (v) {
|
||||
final value = v ?? '';
|
||||
if (value.isEmpty) return 'Indique a sua palavra-passe';
|
||||
if (value.length < 6) return 'Mínimo de 6 caracteres';
|
||||
if (value.isEmpty) return AuthStrings.passwordRequired;
|
||||
if (value.length < 6) return AuthStrings.passwordTooShort;
|
||||
return null;
|
||||
},
|
||||
),
|
||||
@@ -471,7 +473,7 @@ class _AuthForm extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(isLogin ? 'Entrar' : 'Criar Conta'),
|
||||
Text(isLogin ? AuthStrings.login : AuthStrings.createAccount),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.arrow_forward_rounded, size: 18),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user