feat: integrate agent edit profile screen as an embedded tab in profile settings and restrict agent connection actions to non-agent users
This commit is contained in:
@@ -257,6 +257,9 @@ class _AgentDetailScreenState extends ConsumerState<AgentDetailScreen> {
|
|||||||
final agent = state.agent!;
|
final agent = state.agent!;
|
||||||
final isAvailable = agent.isAvailable;
|
final isAvailable = agent.isAvailable;
|
||||||
final connState = state.connectionState;
|
final connState = state.connectionState;
|
||||||
|
// Hide the Connect/Pending/Unlink button when the viewer is an AGENT —
|
||||||
|
// the platform does not support agent-to-agent connections.
|
||||||
|
final viewerIsAgent = ref.watch(authProvider).user?.role == 'AGENT';
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 38),
|
padding: const EdgeInsets.symmetric(horizontal: 38),
|
||||||
@@ -302,18 +305,20 @@ class _AgentDetailScreenState extends ConsumerState<AgentDetailScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
// Connect/Pending/Unlink button
|
// Connect/Pending/Unlink button — hidden for agent viewers
|
||||||
_buildConnectButton(
|
if (!viewerIsAgent) ...[
|
||||||
connState,
|
_buildConnectButton(
|
||||||
isAvailable,
|
connState,
|
||||||
() => _handleConnect(state),
|
isAvailable,
|
||||||
),
|
() => _handleConnect(state),
|
||||||
const SizedBox(width: 4),
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Start Message button when connected
|
// Start Message button when connected (only for non-agent viewers)
|
||||||
if (connState == 'accepted') ...[
|
if (!viewerIsAgent && connState == 'accepted') ...[
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
_buildStartMessageButton(agent),
|
_buildStartMessageButton(agent),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -71,7 +71,11 @@ class _EditProfileData {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class AgentEditProfileScreen extends ConsumerStatefulWidget {
|
class AgentEditProfileScreen extends ConsumerStatefulWidget {
|
||||||
const AgentEditProfileScreen({super.key});
|
/// When true, omits the in-screen back button + title row so this widget can
|
||||||
|
/// be embedded inside another shell (e.g. a tab in ProfileSettingsScreen).
|
||||||
|
final bool embedded;
|
||||||
|
|
||||||
|
const AgentEditProfileScreen({super.key, this.embedded = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<AgentEditProfileScreen> createState() =>
|
ConsumerState<AgentEditProfileScreen> createState() =>
|
||||||
@@ -433,6 +437,10 @@ class _AgentEditProfileScreenState
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final asyncData = ref.watch(_editProfileDataProvider);
|
final asyncData = ref.watch(_editProfileDataProvider);
|
||||||
|
|
||||||
|
if (widget.embedded) {
|
||||||
|
return _buildBody(asyncData);
|
||||||
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
// Header with back button
|
// Header with back button
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:real_estate_mobile/core/constants/app_colors.dart';
|
import 'package:real_estate_mobile/core/constants/app_colors.dart';
|
||||||
|
import 'package:real_estate_mobile/features/agents/presentation/screens/agent_edit_profile_screen.dart';
|
||||||
import 'package:real_estate_mobile/features/profile/presentation/providers/profile_provider.dart';
|
import 'package:real_estate_mobile/features/profile/presentation/providers/profile_provider.dart';
|
||||||
import 'package:real_estate_mobile/features/profile/presentation/widgets/profile_settings_tab.dart';
|
import 'package:real_estate_mobile/features/profile/presentation/widgets/profile_settings_tab.dart';
|
||||||
import 'package:real_estate_mobile/features/profile/presentation/widgets/change_password_tab.dart';
|
import 'package:real_estate_mobile/features/profile/presentation/widgets/change_password_tab.dart';
|
||||||
@@ -18,15 +19,20 @@ class ProfileSettingsScreen extends ConsumerStatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
||||||
int _selectedTab = 0;
|
int? _selectedTab;
|
||||||
|
|
||||||
List<_TabItem> _getTabs(bool isAgent) {
|
List<_TabItem> _getTabs(bool isAgent) {
|
||||||
final tabs = <_TabItem>[
|
final tabs = <_TabItem>[];
|
||||||
|
if (isAgent) {
|
||||||
|
tabs.add(
|
||||||
|
_TabItem(label: 'Edit Profile', icon: Icons.edit_outlined));
|
||||||
|
}
|
||||||
|
tabs.addAll([
|
||||||
_TabItem(label: 'Profile Settings', icon: Icons.person_outline),
|
_TabItem(label: 'Profile Settings', icon: Icons.person_outline),
|
||||||
_TabItem(label: 'Change Password', icon: Icons.lock_outline),
|
_TabItem(label: 'Change Password', icon: Icons.lock_outline),
|
||||||
_TabItem(label: 'Notifications', icon: Icons.notifications_none),
|
_TabItem(label: 'Notifications', icon: Icons.notifications_none),
|
||||||
_TabItem(label: 'Privacy', icon: Icons.shield_outlined),
|
_TabItem(label: 'Privacy', icon: Icons.shield_outlined),
|
||||||
];
|
]);
|
||||||
if (isAgent) {
|
if (isAgent) {
|
||||||
tabs.add(
|
tabs.add(
|
||||||
_TabItem(label: 'Billings & Payments', icon: Icons.payment_outlined));
|
_TabItem(label: 'Billings & Payments', icon: Icons.payment_outlined));
|
||||||
@@ -67,20 +73,24 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
|||||||
|
|
||||||
final tabs = _getTabs(profileState.isAgent);
|
final tabs = _getTabs(profileState.isAgent);
|
||||||
final totalTabs = tabs.length;
|
final totalTabs = tabs.length;
|
||||||
|
// Default tab: Edit Profile (index 0) for agents, Profile Settings (index 0) for users.
|
||||||
|
final selectedTab = (_selectedTab ?? 0).clamp(0, totalTabs - 1);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildTabBar(tabs),
|
_buildTabBar(tabs, selectedTab),
|
||||||
_buildProgressBar(totalTabs),
|
_buildProgressBar(totalTabs, selectedTab),
|
||||||
Expanded(child: _buildSelectedTab(tabs)),
|
Expanded(child: _buildSelectedTab(tabs, selectedTab)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSelectedTab(List<_TabItem> tabs) {
|
Widget _buildSelectedTab(List<_TabItem> tabs, int selectedTab) {
|
||||||
final label = tabs[_selectedTab].label;
|
final label = tabs[selectedTab].label;
|
||||||
switch (label) {
|
switch (label) {
|
||||||
|
case 'Edit Profile':
|
||||||
|
return const AgentEditProfileScreen(embedded: true);
|
||||||
case 'Profile Settings':
|
case 'Profile Settings':
|
||||||
return const ProfileSettingsTab();
|
return const ProfileSettingsTab();
|
||||||
case 'Change Password':
|
case 'Change Password':
|
||||||
@@ -98,7 +108,7 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTabBar(List<_TabItem> tabs) {
|
Widget _buildTabBar(List<_TabItem> tabs, int selectedTab) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 46,
|
height: 46,
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
@@ -106,13 +116,13 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 7),
|
padding: const EdgeInsets.symmetric(horizontal: 7),
|
||||||
itemCount: tabs.length,
|
itemCount: tabs.length,
|
||||||
separatorBuilder: (_, __) => const SizedBox(width: 6),
|
separatorBuilder: (_, __) => const SizedBox(width: 6),
|
||||||
itemBuilder: (_, i) => _buildTab(i, tabs[i]),
|
itemBuilder: (_, i) => _buildTab(i, tabs[i], selectedTab),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTab(int index, _TabItem tab) {
|
Widget _buildTab(int index, _TabItem tab, int selectedTab) {
|
||||||
final isActive = _selectedTab == index;
|
final isActive = selectedTab == index;
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => setState(() => _selectedTab = index),
|
onTap: () => setState(() => _selectedTab = index),
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -153,8 +163,8 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildProgressBar(int totalTabs) {
|
Widget _buildProgressBar(int totalTabs, int selectedTab) {
|
||||||
final progress = (_selectedTab + 1) / totalTabs;
|
final progress = (selectedTab + 1) / totalTabs;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 16),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
|||||||
Reference in New Issue
Block a user