Fixed user management

This commit is contained in:
2026-02-18 20:43:11 +08:00
parent af6cfe76b4
commit 8c1bb7646e
5 changed files with 360 additions and 77 deletions
+60 -6
View File
@@ -6,6 +6,7 @@ import '../../models/profile.dart';
import '../../models/ticket_message.dart';
import '../../models/user_office.dart';
import '../../providers/admin_user_provider.dart';
import '../../providers/auth_provider.dart';
import '../../providers/profile_provider.dart';
import '../../providers/tickets_provider.dart';
import '../../theme/app_surfaces.dart';
@@ -165,7 +166,7 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
return statusAsync.when(
data: (s) => Text(s.email ?? 'Unknown'),
loading: () => const Text('Loading...'),
error: (_, __) => const Text('Unknown'),
error: (error, stack) => const Text('Unknown'),
);
},
),
@@ -190,7 +191,7 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
return _StatusBadge(label: statusLabel);
},
loading: () => _StatusBadge(label: 'Loading'),
error: (_, __) => _StatusBadge(label: 'Unknown'),
error: (error, stack) => _StatusBadge(label: 'Unknown'),
);
},
),
@@ -227,7 +228,7 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
statusAsync.when(
data: (s) => Text('Email: ${s.email ?? 'Unknown'}'),
loading: () => const Text('Email: Loading...'),
error: (_, __) => const Text('Email: Unknown'),
error: (error, stack) => const Text('Email: Unknown'),
),
],
),
@@ -235,7 +236,7 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
data: (s) =>
_StatusBadge(label: s.isLocked ? 'Locked' : 'Active'),
loading: () => _StatusBadge(label: 'Loading'),
error: (_, __) => _StatusBadge(label: 'Unknown'),
error: (error, stack) => _StatusBadge(label: 'Unknown'),
),
onTap: () =>
_showUserDialog(context, profile, offices, assignments),
@@ -286,6 +287,18 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
.map((assignment) => assignment.officeId)
.toSet();
// Populate dialog-backed state so form fields reflect the selected user.
if (mounted) {
setState(() {
_selectedUserId = profile.id;
_selectedRole = profile.role;
_fullNameController.text = profile.fullName;
_selectedOfficeIds
..clear()
..addAll(currentOfficeIds);
});
}
if (!context.mounted) return;
await showDialog<void>(
context: context,
@@ -318,6 +331,17 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
);
},
);
// Clear the temporary selection state after the dialog is closed so the
// next dialog starts from a clean slate.
if (mounted) {
setState(() {
_selectedUserId = null;
_selectedRole = null;
_selectedOfficeIds.clear();
_fullNameController.clear();
});
}
}
Widget _buildUserForm(
@@ -363,7 +387,7 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
'Email: Loading...',
style: Theme.of(context).textTheme.bodySmall,
),
error: (_, __) => Text(
error: (error, stack) => Text(
'Email: Unknown',
style: Theme.of(context).textTheme.bodySmall,
),
@@ -392,7 +416,7 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
icon: const Icon(Icons.lock),
label: const Text('Loading...'),
),
error: (_, __) => OutlinedButton.icon(
error: (error, stack) => OutlinedButton.icon(
onPressed: _isSaving
? null
: () => _toggleLock(profile.id, true),
@@ -578,6 +602,22 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
const SnackBar(content: Text('Password updated.')),
);
} catch (error) {
final msg = error.toString();
if (msg.contains('Unauthorized') ||
msg.contains('bad_jwt') ||
msg.contains('expired')) {
await ref.read(authControllerProvider).signOut();
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Session expired — please sign in again.',
),
),
);
return;
}
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Reset failed: $error')),
@@ -613,6 +653,20 @@ class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
),
);
} catch (error) {
final msg = error.toString();
if (msg.contains('Unauthorized') ||
msg.contains('bad_jwt') ||
msg.contains('expired')) {
await ref.read(authControllerProvider).signOut();
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Session expired — please sign in again.'),
),
);
return;
}
if (!mounted) return;
ScaffoldMessenger.of(
context,