Files
tripz-llc/apps/rider/lib/features/auth/view/name_screen.dart
T

181 lines
6.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../core/l10n/app_localizations.dart';
import '../../../core/design/tokens.dart';
import '../cubit/auth_cubit.dart';
import '../cubit/auth_state.dart';
import '../../../core/ui/tripz_scaffold.dart';
import '../../../core/ui/tripz_button.dart';
import '../../../core/ui/tripz_text_field.dart';
/// شاشة إدخال الاسم (أول دخول فقط) — تطابق stitch/name_entry.html:
/// شعار صغير بالمنتصف أعلى الشاشة + عنوان وسطر فرعي + بطاقة بيضاء
/// مرفوعة فيها حقل الاسم بأيقونة، وزر متابعة أسفل الشاشة.
///
/// ملاحظة: تصميم Stitch يعرض 3 حقول (الاسم الأول/الأخير/البريد)، لكن
/// AuthCubit.updateName ينادي PATCH /users/me بحقل name واحد فقط
/// (docs/29 §3.5 ينص صراحة على «حقل واحد»). الشاشة هنا تستعمل حقلاً
/// واحداً للاسم الكامل بنفس لغة Stitch البصرية (بطاقة مرفوعة + أيقونة
/// + label عائم) دون تغيير عقد الـCubit.
class NameScreen extends StatefulWidget {
const NameScreen({super.key});
@override
State<NameScreen> createState() => _NameScreenState();
}
class _NameScreenState extends State<NameScreen> {
final _firstNameController = TextEditingController();
final _lastNameController = TextEditingController();
bool _valid = false;
@override
void initState() {
super.initState();
_firstNameController.addListener(_validate);
_lastNameController.addListener(_validate);
}
void _validate() {
final isValid = _firstNameController.text.trim().isNotEmpty &&
_lastNameController.text.trim().isNotEmpty;
if (_valid != isValid) {
setState(() => _valid = isValid);
}
}
@override
void dispose() {
_firstNameController.dispose();
_lastNameController.dispose();
super.dispose();
}
void _submit() {
if (!_valid) return;
final fullName =
'${_firstNameController.text.trim()} ${_lastNameController.text.trim()}';
context.read<AuthCubit>().updateName(fullName);
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final theme = Theme.of(context);
final cs = theme.colorScheme;
return BlocConsumer<AuthCubit, AuthState>(
listener: (context, state) {
if (state.status == AuthStatus.error && state.error != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(state.error!)),
);
}
},
builder: (context, state) {
final isLoading = state.status == AuthStatus.authenticating;
return TripzScaffold(
backgroundColor: cs.surfaceContainerLow,
padding: false,
bottomAction: TripzButton(
onPressed: (_valid && !isLoading) ? _submit : null,
label: l10n.nameButton,
loading: isLoading,
),
child: Column(
children: [
// ── رأس الشاشة: زر عودة (يبدأ الجلسة من جديد) + شعار مصغّر ──
SizedBox(
height: T.s48,
child: Row(
children: [
IconButton(
icon: const BackButtonIcon(),
color: cs.onSurface,
tooltip: l10n.back,
onPressed: () => context.read<AuthCubit>().logout(),
),
Expanded(
child: Center(
child: Image.asset(
'assets/images/name_hero.png',
height: T.iconLg,
fit: BoxFit.contain,
errorBuilder: (_, __, ___) => Icon(
Icons.directions_car_filled_rounded,
size: T.iconLg,
color: cs.primary,
),
),
),
),
const SizedBox(width: T.s48),
],
),
),
const SizedBox(height: T.s24),
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: T.pagePadding),
child: Column(
children: [
// العنوان والسطر الفرعي
Text(
l10n.nameTitle,
style: theme.textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w600,
color: cs.onSurface,
),
textAlign: TextAlign.center,
),
const SizedBox(height: T.s8),
Text(
l10n.nameSubtitle,
style: theme.textTheme.bodyLarge?.copyWith(
color: cs.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
const SizedBox(height: T.s24),
// بطاقة بيضاء مرفوعة تحوي حقول الاسم الأول واسم العائلة
Container(
width: double.infinity,
padding: const EdgeInsets.all(T.s24),
decoration: BoxDecoration(
color: cs.surfaceContainerLowest,
borderRadius: BorderRadius.circular(T.r16),
boxShadow: const [T.shadowSm],
),
child: Column(
children: [
TripzTextField(
controller: _firstNameController,
label: l10n.firstNameHint,
autofocus: true,
prefix: Icon(Icons.person_outline_rounded, color: cs.outline),
textInputAction: TextInputAction.next,
),
const SizedBox(height: T.s16),
TripzTextField(
controller: _lastNameController,
label: l10n.lastNameHint,
prefix: Icon(Icons.badge_outlined, color: cs.outline),
onSubmitted: (_) => _submit(),
),
],
),
),
],
),
),
),
],
),
);
},
);
}
}