feat: Implement optimistic UI for agent availability toggle, add email and phone visibility toggles, and improve the logout process with immediate socket disconnection and best-effort API calls.

This commit is contained in:
pradeepkumar
2026-03-15 00:35:39 +05:30
parent 54fdd66270
commit 21f669fca5
6 changed files with 104 additions and 14 deletions

View File

@@ -87,6 +87,8 @@ class _AgentHomeContent extends ConsumerStatefulWidget {
class _AgentHomeContentState extends ConsumerState<_AgentHomeContent> {
bool _isUploadingAvatar = false;
bool _isTogglingAvailability = false;
bool _showEmail = false;
bool _showPhone = false;
File? _localAvatarFile;
Future<void> _pickAndUploadAvatar() async {
@@ -179,13 +181,21 @@ class _AgentHomeContentState extends ConsumerState<_AgentHomeContent> {
if (_isTogglingAvailability) return;
setState(() => _isTogglingAvailability = true);
// Optimistically update the UI immediately
ref
.read(agentDetailProvider(widget.agentProfileId).notifier)
.updateAvailability(newValue);
try {
final repo = ProfileRepository();
await repo.updateProfile('AGENT', {'isAvailable': newValue});
// Refresh agent detail to reflect new status
ref.invalidate(agentDetailProvider(widget.agentProfileId));
} catch (e) {
// Revert on failure
if (mounted) {
ref
.read(agentDetailProvider(widget.agentProfileId).notifier)
.updateAvailability(!newValue);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to update availability: $e')),
);
@@ -475,15 +485,32 @@ class _AgentHomeContentState extends ConsumerState<_AgentHomeContent> {
const SizedBox(width: 16),
Expanded(
child: Text(
email.isNotEmpty ? state.maskEmail(email) : '-',
email.isNotEmpty
? (_showEmail ? email : state.maskEmail(email))
: '-',
style: const TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
color: AppColors.primaryDark),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
const Icon(Icons.visibility_off_outlined,
size: 18, color: AppColors.primaryDark),
if (email.isNotEmpty)
GestureDetector(
onTap: () => setState(() => _showEmail = !_showEmail),
behavior: HitTestBehavior.opaque,
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(
_showEmail
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
size: 18,
color: AppColors.primaryDark,
),
),
),
],
),
const SizedBox(height: 14),
@@ -498,15 +525,32 @@ class _AgentHomeContentState extends ConsumerState<_AgentHomeContent> {
const SizedBox(width: 16),
Expanded(
child: Text(
phone.isNotEmpty ? state.maskPhone(phone) : '-',
phone.isNotEmpty
? (_showPhone ? phone : state.maskPhone(phone))
: '-',
style: const TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
color: AppColors.primaryDark),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
const Icon(Icons.visibility_off_outlined,
size: 18, color: AppColors.primaryDark),
if (phone.isNotEmpty)
GestureDetector(
onTap: () => setState(() => _showPhone = !_showPhone),
behavior: HitTestBehavior.opaque,
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(
_showPhone
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
size: 18,
color: AppColors.primaryDark,
),
),
),
],
),
],