Chepuhagram/lib/presentation/screens/account_settings_screen.dart

207 lines
7.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:chepuhagram/domain/services/api_service.dart';
import 'package:chepuhagram/logic/auth_provider.dart';
class AccountSettingsScreen extends StatefulWidget {
const AccountSettingsScreen({super.key});
@override
State<AccountSettingsScreen> createState() => _AccountSettingsScreenState();
}
class _AccountSettingsScreenState extends State<AccountSettingsScreen> {
final _formKey = GlobalKey<FormState>();
final _usernameController = TextEditingController();
final _firstNameController = TextEditingController();
final _lastNameController = TextEditingController();
final _phoneController = TextEditingController();
final _emailController = TextEditingController();
final _aboutController = TextEditingController();
bool _isSaving = false;
@override
void initState() {
super.initState();
final auth = context.read<AuthProvider>();
_usernameController.text = auth.username ?? '';
_firstNameController.text = auth.firstName ?? '';
_lastNameController.text = auth.lastName ?? '';
_phoneController.text = auth.phone ?? '';
_emailController.text = auth.email ?? '';
_aboutController.text = auth.about ?? '';
}
@override
void dispose() {
_usernameController.dispose();
_firstNameController.dispose();
_lastNameController.dispose();
_phoneController.dispose();
_emailController.dispose();
_aboutController.dispose();
super.dispose();
}
Future<void> _save() async {
if (!_formKey.currentState!.validate()) return;
setState(() => _isSaving = true);
try {
final api = ApiService();
await api.updateMe(
username: _usernameController.text.trim(),
firstName: _firstNameController.text.trim(),
lastName: _lastNameController.text.trim(),
phone: _phoneController.text,
email: _emailController.text,
about: _aboutController.text,
);
if (!mounted) return;
await context.read<AuthProvider>().refreshMe();
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Сохранено'), behavior: SnackBarBehavior.floating),
);
Navigator.of(context).pop();
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toString().replaceAll('Exception: ', '')), behavior: SnackBarBehavior.floating),
);
} finally {
if (mounted) setState(() => _isSaving = false);
}
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
backgroundColor: colorScheme.background,
appBar: AppBar(
title: const Text('Редактировать аккаунт', style: TextStyle(fontWeight: FontWeight.bold)),
elevation: 0,
backgroundColor: Colors.transparent,
actions: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Center(
child: _isSaving
? SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2.5, color: colorScheme.primary),
)
: TextButton.icon(
onPressed: _save,
icon: const Icon(Icons.done_rounded, size: 18),
label: const Text('Готово', style: TextStyle(fontWeight: FontWeight.bold)),
),
),
),
],
),
body: Form(
key: _formKey,
child: ListView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
children: [
_buildInputField(
controller: _usernameController,
label: 'Имя пользователя',
hint: 'Латиница, цифры, подчеркивания',
icon: Icons.alternate_email_rounded,
validator: (v) {
if (v == null || v.trim().isEmpty) return 'Введите имя пользователя';
if (!RegExp(r'^[a-zA-Z0-9_]{3,20}$').hasMatch(v.trim())) {
return 'От 3 до 20 символов (A-Z, 0-9, _)';
}
return null;
},
),
_buildInputField(
controller: _firstNameController,
label: 'Имя',
hint: 'Введите ваше имя',
icon: Icons.person_outline_rounded,
validator: (v) {
if (v == null || v.trim().isEmpty) return 'Введите имя';
return null;
},
),
_buildInputField(
controller: _lastNameController,
label: 'Фамилия',
hint: 'Введите вашу фамилию',
icon: Icons.people_outline_rounded,
),
_buildInputField(
controller: _phoneController,
label: 'Телефон',
hint: 'Номер телефона',
icon: Icons.phone_android_rounded,
keyboardType: TextInputType.phone,
),
_buildInputField(
controller: _emailController,
label: 'Почта',
hint: 'Электронный адрес',
icon: Icons.mail_outline_rounded,
keyboardType: TextInputType.emailAddress,
),
_buildInputField(
controller: _aboutController,
label: 'О себе',
hint: 'Расскажите немного о себе',
icon: Icons.short_text_rounded,
maxLines: 4,
),
],
),
),
);
}
Widget _buildInputField({
required TextEditingController controller,
required String label,
required String hint,
required IconData icon,
int maxLines = 1,
TextInputType? keyboardType,
String? Function(String?)? validator,
}) {
final colorScheme = Theme.of(context).colorScheme;
return Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: Container(
decoration: BoxDecoration(
color: colorScheme.surfaceVariant.withOpacity(0.15),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: colorScheme.outlineVariant.withOpacity(0.1)),
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
child: TextFormField(
controller: controller,
maxLines: maxLines,
keyboardType: keyboardType,
validator: validator,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
decoration: InputDecoration(
icon: Icon(icon, color: colorScheme.primary, size: 22),
labelText: label,
labelStyle: TextStyle(color: colorScheme.outline, fontSize: 14),
hintText: hint,
hintStyle: TextStyle(color: colorScheme.outline.withOpacity(0.5)),
border: InputBorder.none,
errorStyle: TextStyle(color: colorScheme.error, fontWeight: FontWeight.w500),
),
),
),
);
}
}