Atualição da appbar | coreção de inserção de dados | outras optimizaçoes
This commit is contained in:
@@ -15,9 +15,13 @@ import 'screens/settings_screen.dart';
|
||||
import 'screens/video_screen.dart';
|
||||
import 'widgets/animated_nav_icon.dart';
|
||||
import 'widgets/app_dialogs.dart';
|
||||
import 'widgets/app_gradients.dart';
|
||||
import 'widgets/entrance.dart';
|
||||
import 'widgets/tap_bounce.dart';
|
||||
|
||||
/// Nomes só podem ter letras (incluindo acentuadas) e espaços — sem números.
|
||||
final RegExp _namePattern = RegExp(r"^[a-zA-ZÀ-ÖØ-öø-ÿ' -]+$");
|
||||
|
||||
class LoggedHomeScreen extends StatefulWidget {
|
||||
const LoggedHomeScreen({super.key});
|
||||
|
||||
@@ -249,7 +253,13 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
child: AppBar(
|
||||
toolbarHeight: toolbarHeight,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
flexibleSpace: _index != 0
|
||||
flexibleSpace: ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
bottom: Radius.circular(_index == 0 ? 24 : 0),
|
||||
),
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(gradient: kAppBarGradient),
|
||||
child: _index != 0
|
||||
? null
|
||||
: Stack(
|
||||
fit: StackFit.expand,
|
||||
@@ -304,6 +314,8 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
title: Align(
|
||||
alignment: _index == 0 ? Alignment.topLeft : Alignment.center,
|
||||
child: _index == 0
|
||||
@@ -735,70 +747,83 @@ Future<Map<String, dynamic>?> _pickChildSheet(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
builder: (ctx) {
|
||||
final maxHeight = MediaQuery.sizeOf(ctx).height * 0.8;
|
||||
return SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(18, 6, 18, 18),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Text(
|
||||
'Para qual criança é o quiz?',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Color(0xFFFF55A7),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxHeight: maxHeight),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(18, 6, 18, 18),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Text(
|
||||
'Para qual criança é o quiz?',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Color(0xFFFF55A7),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
...children.map((c) {
|
||||
final name = (c['name'] ?? '').toString();
|
||||
final age = c['age'];
|
||||
final label = age != null ? '$name • $age anos' : name;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: TapBounce(
|
||||
scale: 0.97,
|
||||
child: Material(
|
||||
color: Colors.white.withValues(alpha: 0.85),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => Navigator.of(ctx).pop(c),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w800,
|
||||
const SizedBox(height: 14),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: children.map((c) {
|
||||
final name = (c['name'] ?? '').toString();
|
||||
final age = c['age'];
|
||||
final label = age != null
|
||||
? '$name • $age anos'
|
||||
: name;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: TapBounce(
|
||||
scale: 0.97,
|
||||
child: Material(
|
||||
color: Colors.white.withValues(alpha: 0.85),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => Navigator.of(ctx).pop(c),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.chevron_right_rounded,
|
||||
color: teal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.chevron_right_rounded,
|
||||
color: teal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
const SizedBox(height: 4),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(null),
|
||||
child: const Text('Cancelar'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(null),
|
||||
child: const Text('Cancelar'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -1824,6 +1849,9 @@ class _AddChildSheetState extends State<_AddChildSheet> {
|
||||
final value = (v ?? '').trim();
|
||||
if (value.isEmpty) return 'Informe o nome';
|
||||
if (value.length < 2) return 'Nome muito curto';
|
||||
if (!_namePattern.hasMatch(value)) {
|
||||
return 'O nome não pode conter números';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
@@ -1831,13 +1859,19 @@ class _AddChildSheetState extends State<_AddChildSheet> {
|
||||
controller: _ageController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.next,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
LengthLimitingTextInputFormatter(2),
|
||||
],
|
||||
decoration: const InputDecoration(labelText: 'Idade'),
|
||||
validator: (v) {
|
||||
final raw = (v ?? '').trim();
|
||||
if (raw.isEmpty) return 'Informe a idade';
|
||||
final age = int.tryParse(raw);
|
||||
if (age == null) return 'Idade inválida';
|
||||
if (age < 0 || age > 25) return 'Idade inválida';
|
||||
if (age < 0 || age > 17) {
|
||||
return 'Idade deve ser entre 0 e 17 anos';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user