feat: implement email change request functionality with verification dialog

This commit is contained in:
pradeepkumar
2026-04-20 14:07:37 +05:30
parent 6b0fa24b85
commit 3c61c25f5e
2 changed files with 158 additions and 5 deletions

View File

@@ -256,11 +256,37 @@ class _ProfileSettingsTabState extends ConsumerState<ProfileSettingsTab> {
),
],
const SizedBox(height: 24),
ProfileFormField(
label: 'Email Address',
controller: _emailController,
enabled: false,
textCapitalization: TextCapitalization.none),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: ProfileFormField(
label: 'Email Address',
controller: _emailController,
enabled: false,
textCapitalization: TextCapitalization.none),
),
const SizedBox(width: 8),
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: TextButton(
onPressed: _openChangeEmailDialog,
style: TextButton.styleFrom(
foregroundColor: AppColors.accentOrange,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
),
child: const Text(
'Change',
style: TextStyle(
fontFamily: 'SourceSerif4',
fontWeight: FontWeight.w600,
fontSize: 13,
),
),
),
),
],
),
const SizedBox(height: 24),
ProfileFormField(
label: 'Phone Number',
@@ -403,4 +429,109 @@ class _ProfileSettingsTabState extends ConsumerState<ProfileSettingsTab> {
),
);
}
Future<void> _openChangeEmailDialog() async {
final newEmailCtl = TextEditingController();
final passwordCtl = TextEditingController();
String? localError;
bool submitting = false;
await showDialog<void>(
context: context,
builder: (dialogCtx) {
return StatefulBuilder(
builder: (dialogCtx, setDialogState) {
Future<void> submit() async {
final email = newEmailCtl.text.trim();
final pw = passwordCtl.text;
if (email.isEmpty || pw.isEmpty) {
setDialogState(() => localError =
'Please enter a new email and your current password');
return;
}
setDialogState(() {
submitting = true;
localError = null;
});
try {
final repo = ref.read(profileRepositoryProvider);
final message = await repo.requestEmailChange(email, pw);
if (dialogCtx.mounted) Navigator.of(dialogCtx).pop();
if (mounted) _showSnackBar(message);
} catch (e) {
setDialogState(() {
submitting = false;
localError = e.toString().replaceFirst('Exception: ', '');
});
}
}
return AlertDialog(
title: const Text('Change Email Address'),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'A verification link will be sent to your new email. Your email changes only after you click the link.',
style: TextStyle(fontSize: 13),
),
const SizedBox(height: 16),
TextField(
controller: newEmailCtl,
keyboardType: TextInputType.emailAddress,
autocorrect: false,
textCapitalization: TextCapitalization.none,
decoration: const InputDecoration(
labelText: 'New Email',
hintText: 'new@example.com',
),
),
const SizedBox(height: 12),
TextField(
controller: passwordCtl,
obscureText: true,
decoration: const InputDecoration(
labelText: 'Current Password',
),
),
if (localError != null) ...[
const SizedBox(height: 12),
Text(
localError!,
style: const TextStyle(
color: Colors.red,
fontSize: 12,
),
),
],
],
),
),
actions: [
TextButton(
onPressed: submitting
? null
: () => Navigator.of(dialogCtx).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: submitting ? null : submit,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.accentOrange,
foregroundColor: Colors.white,
),
child: Text(submitting ? 'Sending...' : 'Send Link'),
),
],
);
},
);
},
);
newEmailCtl.dispose();
passwordCtl.dispose();
}
}