Files
sendico/frontend/pweb/lib/pages/settings/profile/account/name.dart
2025-12-18 15:15:33 +03:00

178 lines
5.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pweb/models/edit_state.dart';
import 'package:pshared/provider/account.dart';
class AccountName extends StatefulWidget {
final String name;
final String title;
final String hintText;
final String errorText;
const AccountName({
super.key,
required this.name,
required this.title,
required this.hintText,
required this.errorText,
});
@override
State<AccountName> createState() => _AccountNameState();
}
class _AccountNameState extends State<AccountName> {
static const double _inputWidth = 200;
static const double _spacing = 8;
static const double _errorSpacing = 4;
static const double _borderWidth = 2;
late final TextEditingController _controller;
EditState _editState = EditState.view;
late String _originalName;
String _errorText = '';
@override
void initState() {
super.initState();
_controller = TextEditingController(text: widget.name);
_originalName = widget.name;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _startEditing() => setState(() => _editState = EditState.edit);
void _cancelEditing() {
setState(() {
_controller.text = _originalName;
_editState = EditState.view;
_errorText = '';
});
}
Future<void> _saveEditing(AccountProvider provider) async {
final newName = _controller.text.trim();
if (newName.isEmpty || newName == _originalName) {
_cancelEditing();
return;
}
setState(() {
_editState = EditState.saving;
_errorText = '';
});
try {
await provider.resetUsername(newName);
if (!mounted) return;
setState(() {
_originalName = newName;
_editState = EditState.view;
});
} catch (_) {
if (!mounted) return;
setState(() {
_errorText = widget.errorText;
_editState = EditState.edit;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(widget.errorText)),
);
return;
} finally {
if (!mounted) return;
if (_editState == EditState.saving) {
setState(() => _editState = EditState.edit);
}
}
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Consumer<AccountProvider>(
builder: (context, provider, _) {
final isEditing = _editState != EditState.view;
final currentName = provider.account?.name ?? _originalName;
final isBusy = provider.isLoading || _editState == EditState.saving;
if (!isEditing && currentName != _originalName) {
_originalName = currentName;
_controller.text = currentName;
}
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (isEditing)
SizedBox(
width: _inputWidth,
child: TextFormField(
controller: _controller,
style: theme.textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.bold,
),
autofocus: true,
enabled: !isBusy,
decoration: InputDecoration(
hintText: widget.hintText,
isDense: true,
border: UnderlineInputBorder(
borderSide: BorderSide(
color: theme.colorScheme.primary,
width: _borderWidth,
),
),
),
),
)
else
Text(
_originalName,
style: theme.textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: _spacing),
if (isEditing) ...[
IconButton(
icon: Icon(Icons.check, color: theme.colorScheme.primary),
onPressed: isBusy ? null : () => _saveEditing(provider),
),
IconButton(
icon: Icon(Icons.close, color: theme.colorScheme.error),
onPressed: isBusy ? null : _cancelEditing,
),
] else
IconButton(
icon: Icon(Icons.edit, color: theme.colorScheme.primary),
onPressed: isBusy ? null : _startEditing,
),
],
),
const SizedBox(height: _errorSpacing),
if (_errorText.isNotEmpty)
Text(
_errorText,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.error,
),
),
],
);
},
);
}
}