feat: Add optional agentTypeId field to RegisterRequest model.
This commit is contained in:
@@ -624,70 +624,83 @@ class _AgentDetailScreenState extends ConsumerState<AgentDetailScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
// Location + Member Since (same line, matching web ProfileCard)
|
// Location (wrapping) + Member Since (separate line)
|
||||||
Builder(builder: (_) {
|
Builder(builder: (_) {
|
||||||
final parts = state.locationParts;
|
final parts = state.locationParts;
|
||||||
const maxVisible = 1;
|
const maxVisible = 4;
|
||||||
final firstPart = parts.isNotEmpty ? parts.first : '';
|
final visibleParts = parts.take(maxVisible).join(', ');
|
||||||
final remaining = parts.length - maxVisible;
|
final remaining = parts.length - maxVisible;
|
||||||
|
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
if (parts.isNotEmpty) ...[
|
if (parts.isNotEmpty) ...[
|
||||||
SvgPicture.asset(
|
GestureDetector(
|
||||||
'assets/icons/location_pin_icon.svg',
|
onTap: remaining > 0 ? () => _showLocationModal(parts) : null,
|
||||||
width: 18,
|
child: Row(
|
||||||
height: 18,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 2),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
'assets/icons/location_pin_icon.svg',
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Flexible(
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: visibleParts,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily: 'SourceSerif4',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColors.primaryDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (remaining > 0)
|
||||||
|
TextSpan(
|
||||||
|
text: ' +$remaining more',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily: 'SourceSerif4',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.accentOrange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(height: 6),
|
||||||
ConstrainedBox(
|
],
|
||||||
constraints: const BoxConstraints(maxWidth: 120),
|
Row(
|
||||||
child: Text(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
firstPart,
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
'assets/icons/calendar_icon.svg',
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
agent.memberSinceText,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontFamily: 'SourceSerif4',
|
fontFamily: 'SourceSerif4',
|
||||||
fontSize: 14,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w500,
|
||||||
color: AppColors.primaryDark,
|
color: AppColors.primaryDark,
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
if (remaining > 0)
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () => _showLocationModal(parts),
|
|
||||||
child: Text(
|
|
||||||
' +$remaining more',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontFamily: 'SourceSerif4',
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: AppColors.accentOrange,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
],
|
|
||||||
SvgPicture.asset(
|
|
||||||
'assets/icons/calendar_icon.svg',
|
|
||||||
width: 18,
|
|
||||||
height: 18,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
agent.memberSinceText,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontFamily: 'SourceSerif4',
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: AppColors.primaryDark,
|
|
||||||
),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ abstract class RegisterRequest with _$RegisterRequest {
|
|||||||
required String role,
|
required String role,
|
||||||
String? firstName,
|
String? firstName,
|
||||||
String? lastName,
|
String? lastName,
|
||||||
|
String? agentTypeId,
|
||||||
}) = _RegisterRequest;
|
}) = _RegisterRequest;
|
||||||
|
|
||||||
factory RegisterRequest.fromJson(Map<String, dynamic> json) =>
|
factory RegisterRequest.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$RegisterRequest {
|
mixin _$RegisterRequest {
|
||||||
|
|
||||||
String get email; String get password; String get role; String? get firstName; String? get lastName;
|
String get email; String get password; String get role; String? get firstName; String? get lastName; String? get agentTypeId;
|
||||||
/// Create a copy of RegisterRequest
|
/// Create a copy of RegisterRequest
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $RegisterRequestCopyWith<RegisterRequest> get copyWith => _$RegisterRequestCopyW
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is RegisterRequest&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.role, role) || other.role == role)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is RegisterRequest&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.role, role) || other.role == role)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.agentTypeId, agentTypeId) || other.agentTypeId == agentTypeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,email,password,role,firstName,lastName);
|
int get hashCode => Object.hash(runtimeType,email,password,role,firstName,lastName,agentTypeId);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'RegisterRequest(email: $email, password: $password, role: $role, firstName: $firstName, lastName: $lastName)';
|
return 'RegisterRequest(email: $email, password: $password, role: $role, firstName: $firstName, lastName: $lastName, agentTypeId: $agentTypeId)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $RegisterRequestCopyWith<$Res> {
|
|||||||
factory $RegisterRequestCopyWith(RegisterRequest value, $Res Function(RegisterRequest) _then) = _$RegisterRequestCopyWithImpl;
|
factory $RegisterRequestCopyWith(RegisterRequest value, $Res Function(RegisterRequest) _then) = _$RegisterRequestCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String email, String password, String role, String? firstName, String? lastName
|
String email, String password, String role, String? firstName, String? lastName, String? agentTypeId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,13 +65,14 @@ class _$RegisterRequestCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of RegisterRequest
|
/// Create a copy of RegisterRequest
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? email = null,Object? password = null,Object? role = null,Object? firstName = freezed,Object? lastName = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? email = null,Object? password = null,Object? role = null,Object? firstName = freezed,Object? lastName = freezed,Object? agentTypeId = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||||
as String,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
as String,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
||||||
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,agentTypeId: freezed == agentTypeId ? _self.agentTypeId : agentTypeId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,
|
as String?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -157,10 +158,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String email, String password, String role, String? firstName, String? lastName)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String email, String password, String role, String? firstName, String? lastName, String? agentTypeId)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _RegisterRequest() when $default != null:
|
case _RegisterRequest() when $default != null:
|
||||||
return $default(_that.email,_that.password,_that.role,_that.firstName,_that.lastName);case _:
|
return $default(_that.email,_that.password,_that.role,_that.firstName,_that.lastName,_that.agentTypeId);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -178,10 +179,10 @@ return $default(_that.email,_that.password,_that.role,_that.firstName,_that.last
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String email, String password, String role, String? firstName, String? lastName) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String email, String password, String role, String? firstName, String? lastName, String? agentTypeId) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _RegisterRequest():
|
case _RegisterRequest():
|
||||||
return $default(_that.email,_that.password,_that.role,_that.firstName,_that.lastName);case _:
|
return $default(_that.email,_that.password,_that.role,_that.firstName,_that.lastName,_that.agentTypeId);case _:
|
||||||
throw StateError('Unexpected subclass');
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -198,10 +199,10 @@ return $default(_that.email,_that.password,_that.role,_that.firstName,_that.last
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String email, String password, String role, String? firstName, String? lastName)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String email, String password, String role, String? firstName, String? lastName, String? agentTypeId)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _RegisterRequest() when $default != null:
|
case _RegisterRequest() when $default != null:
|
||||||
return $default(_that.email,_that.password,_that.role,_that.firstName,_that.lastName);case _:
|
return $default(_that.email,_that.password,_that.role,_that.firstName,_that.lastName,_that.agentTypeId);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -213,7 +214,7 @@ return $default(_that.email,_that.password,_that.role,_that.firstName,_that.last
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _RegisterRequest implements RegisterRequest {
|
class _RegisterRequest implements RegisterRequest {
|
||||||
const _RegisterRequest({required this.email, required this.password, required this.role, this.firstName, this.lastName});
|
const _RegisterRequest({required this.email, required this.password, required this.role, this.firstName, this.lastName, this.agentTypeId});
|
||||||
factory _RegisterRequest.fromJson(Map<String, dynamic> json) => _$RegisterRequestFromJson(json);
|
factory _RegisterRequest.fromJson(Map<String, dynamic> json) => _$RegisterRequestFromJson(json);
|
||||||
|
|
||||||
@override final String email;
|
@override final String email;
|
||||||
@@ -221,6 +222,7 @@ class _RegisterRequest implements RegisterRequest {
|
|||||||
@override final String role;
|
@override final String role;
|
||||||
@override final String? firstName;
|
@override final String? firstName;
|
||||||
@override final String? lastName;
|
@override final String? lastName;
|
||||||
|
@override final String? agentTypeId;
|
||||||
|
|
||||||
/// Create a copy of RegisterRequest
|
/// Create a copy of RegisterRequest
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -235,16 +237,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RegisterRequest&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.role, role) || other.role == role)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RegisterRequest&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.role, role) || other.role == role)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.agentTypeId, agentTypeId) || other.agentTypeId == agentTypeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,email,password,role,firstName,lastName);
|
int get hashCode => Object.hash(runtimeType,email,password,role,firstName,lastName,agentTypeId);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'RegisterRequest(email: $email, password: $password, role: $role, firstName: $firstName, lastName: $lastName)';
|
return 'RegisterRequest(email: $email, password: $password, role: $role, firstName: $firstName, lastName: $lastName, agentTypeId: $agentTypeId)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -255,7 +257,7 @@ abstract mixin class _$RegisterRequestCopyWith<$Res> implements $RegisterRequest
|
|||||||
factory _$RegisterRequestCopyWith(_RegisterRequest value, $Res Function(_RegisterRequest) _then) = __$RegisterRequestCopyWithImpl;
|
factory _$RegisterRequestCopyWith(_RegisterRequest value, $Res Function(_RegisterRequest) _then) = __$RegisterRequestCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String email, String password, String role, String? firstName, String? lastName
|
String email, String password, String role, String? firstName, String? lastName, String? agentTypeId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -272,13 +274,14 @@ class __$RegisterRequestCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of RegisterRequest
|
/// Create a copy of RegisterRequest
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? email = null,Object? password = null,Object? role = null,Object? firstName = freezed,Object? lastName = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? email = null,Object? password = null,Object? role = null,Object? firstName = freezed,Object? lastName = freezed,Object? agentTypeId = freezed,}) {
|
||||||
return _then(_RegisterRequest(
|
return _then(_RegisterRequest(
|
||||||
email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||||
as String,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
as String,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
||||||
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,agentTypeId: freezed == agentTypeId ? _self.agentTypeId : agentTypeId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,
|
as String?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ _RegisterRequest _$RegisterRequestFromJson(Map<String, dynamic> json) =>
|
|||||||
role: json['role'] as String,
|
role: json['role'] as String,
|
||||||
firstName: json['firstName'] as String?,
|
firstName: json['firstName'] as String?,
|
||||||
lastName: json['lastName'] as String?,
|
lastName: json['lastName'] as String?,
|
||||||
|
agentTypeId: json['agentTypeId'] as String?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$RegisterRequestToJson(_RegisterRequest instance) =>
|
Map<String, dynamic> _$RegisterRequestToJson(_RegisterRequest instance) =>
|
||||||
@@ -22,4 +23,5 @@ Map<String, dynamic> _$RegisterRequestToJson(_RegisterRequest instance) =>
|
|||||||
'role': instance.role,
|
'role': instance.role,
|
||||||
'firstName': instance.firstName,
|
'firstName': instance.firstName,
|
||||||
'lastName': instance.lastName,
|
'lastName': instance.lastName,
|
||||||
|
'agentTypeId': instance.agentTypeId,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
|||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
required String role,
|
required String role,
|
||||||
|
String? agentTypeId,
|
||||||
}) async {
|
}) async {
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
status: AuthStatus.loading,
|
status: AuthStatus.loading,
|
||||||
@@ -188,6 +189,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
|||||||
role: role,
|
role: role,
|
||||||
firstName: firstName,
|
firstName: firstName,
|
||||||
lastName: lastName,
|
lastName: lastName,
|
||||||
|
agentTypeId: role == 'AGENT' ? agentTypeId : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
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/data/models/agent_type.dart';
|
||||||
|
import 'package:real_estate_mobile/features/agents/presentation/providers/agents_provider.dart';
|
||||||
import 'package:real_estate_mobile/features/auth/presentation/providers/auth_provider.dart';
|
import 'package:real_estate_mobile/features/auth/presentation/providers/auth_provider.dart';
|
||||||
import 'package:real_estate_mobile/features/auth/presentation/widgets/auth_text_field.dart';
|
import 'package:real_estate_mobile/features/auth/presentation/widgets/auth_text_field.dart';
|
||||||
import 'package:real_estate_mobile/features/auth/presentation/widgets/or_divider.dart';
|
import 'package:real_estate_mobile/features/auth/presentation/widgets/or_divider.dart';
|
||||||
@@ -22,6 +24,16 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
String _selectedRole = 'USER';
|
String _selectedRole = 'USER';
|
||||||
bool _obscurePassword = true;
|
bool _obscurePassword = true;
|
||||||
|
|
||||||
|
List<AgentType> _agentTypes = [];
|
||||||
|
String? _selectedAgentTypeId;
|
||||||
|
bool _loadingAgentTypes = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_fetchAgentTypes();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_nameController.dispose();
|
_nameController.dispose();
|
||||||
@@ -30,6 +42,22 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchAgentTypes() async {
|
||||||
|
setState(() => _loadingAgentTypes = true);
|
||||||
|
try {
|
||||||
|
final repo = ref.read(agentsRepositoryProvider);
|
||||||
|
final types = await repo.getAgentTypes();
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_agentTypes = types;
|
||||||
|
_loadingAgentTypes = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
if (mounted) setState(() => _loadingAgentTypes = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String? _validateLocally() {
|
String? _validateLocally() {
|
||||||
if (_nameController.text.trim().isEmpty) {
|
if (_nameController.text.trim().isEmpty) {
|
||||||
return 'Please enter your name';
|
return 'Please enter your name';
|
||||||
@@ -40,6 +68,9 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
if (_passwordController.text.isEmpty) {
|
if (_passwordController.text.isEmpty) {
|
||||||
return 'Please enter a password';
|
return 'Please enter a password';
|
||||||
}
|
}
|
||||||
|
if (_selectedRole == 'AGENT' && (_selectedAgentTypeId == null || _selectedAgentTypeId!.isEmpty)) {
|
||||||
|
return 'Please select an agent type';
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +91,7 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
email: _emailController.text.trim(),
|
email: _emailController.text.trim(),
|
||||||
password: _passwordController.text,
|
password: _passwordController.text,
|
||||||
role: _selectedRole,
|
role: _selectedRole,
|
||||||
|
agentTypeId: _selectedRole == 'AGENT' ? _selectedAgentTypeId : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,19 +238,10 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
// Role toggle
|
// Role toggle
|
||||||
RoleToggle(
|
RoleToggle(
|
||||||
selectedRole: _selectedRole,
|
selectedRole: _selectedRole,
|
||||||
onChanged: (role) => setState(() => _selectedRole = role),
|
onChanged: (role) => setState(() {
|
||||||
),
|
_selectedRole = role;
|
||||||
const SizedBox(height: 20),
|
if (role != 'AGENT') _selectedAgentTypeId = null;
|
||||||
|
}),
|
||||||
// Subtitle
|
|
||||||
Text(
|
|
||||||
'Enter Your Name to Continue',
|
|
||||||
style: TextStyle(
|
|
||||||
fontFamily: 'Fractul',
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w300,
|
|
||||||
color: AppColors.primaryDark.withValues(alpha: 0.7),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
@@ -296,6 +319,76 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Agent type selector (only when AGENT role is selected)
|
||||||
|
if (_selectedRole == 'AGENT') ...[
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Container(
|
||||||
|
height: 50,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: _loadingAgentTypes
|
||||||
|
? const Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
color: AppColors.accentOrange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton<String>(
|
||||||
|
value: _selectedAgentTypeId,
|
||||||
|
hint: Text(
|
||||||
|
'Select Agent Type',
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: 'Fractul',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w300,
|
||||||
|
color: AppColors.primaryDark.withValues(alpha: 0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
isExpanded: true,
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.keyboard_arrow_down,
|
||||||
|
color: AppColors.primaryDark,
|
||||||
|
size: 22,
|
||||||
|
),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily: 'Fractul',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: AppColors.primaryDark,
|
||||||
|
),
|
||||||
|
items: _agentTypes
|
||||||
|
.map((type) => DropdownMenuItem<String>(
|
||||||
|
value: type.id,
|
||||||
|
child: Text(type.name),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
onChanged: (value) =>
|
||||||
|
setState(() => _selectedAgentTypeId = value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (authState.getFieldError('agentTypeId') != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 6, left: 12),
|
||||||
|
child: Text(
|
||||||
|
authState.getFieldError('agentTypeId')!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily: 'Fractul',
|
||||||
|
fontSize: 12,
|
||||||
|
color: AppColors.error,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
// Sign Up button
|
// Sign Up button
|
||||||
|
|||||||
@@ -50,9 +50,19 @@ class _HeroSectionState extends ConsumerState<HeroSection> {
|
|||||||
if (_selectedLocation != null) params['location'] = Uri.encodeComponent(_selectedLocation!);
|
if (_selectedLocation != null) params['location'] = Uri.encodeComponent(_selectedLocation!);
|
||||||
if (_selectedCategory != null) params['category'] = Uri.encodeComponent(_selectedCategory!);
|
if (_selectedCategory != null) params['category'] = Uri.encodeComponent(_selectedCategory!);
|
||||||
|
|
||||||
|
if (params.isEmpty) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Please select at least one filter to search'),
|
||||||
|
backgroundColor: AppColors.accentOrange,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final queryString =
|
final queryString =
|
||||||
params.entries.map((e) => '${e.key}=${e.value}').join('&');
|
params.entries.map((e) => '${e.key}=${e.value}').join('&');
|
||||||
context.push('/agents/search${queryString.isNotEmpty ? '?$queryString' : ''}');
|
context.push('/agents/search?$queryString');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showTypePicker() async {
|
Future<void> _showTypePicker() async {
|
||||||
|
|||||||
@@ -341,20 +341,30 @@ class _MenuDrawer extends ConsumerWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: const [
|
children: [
|
||||||
Icon(
|
SizedBox(
|
||||||
Icons.logout_rounded,
|
height: 20,
|
||||||
color: AppColors.primaryDark,
|
width: 20,
|
||||||
size: 20,
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.logout_rounded,
|
||||||
|
color: AppColors.primaryDark,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
const Padding(
|
||||||
'Log Out',
|
padding: EdgeInsets.only(top: 1),
|
||||||
style: TextStyle(
|
child: Text(
|
||||||
fontFamily: 'Fractul',
|
'Log Out',
|
||||||
fontSize: 14,
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontFamily: 'Fractul',
|
||||||
color: AppColors.primaryDark,
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColors.primaryDark,
|
||||||
|
height: 1.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -366,25 +376,11 @@ class _MenuDrawer extends ConsumerWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 54,
|
height: 54,
|
||||||
child: ElevatedButton.icon(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
context.push('/login');
|
context.push('/login');
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
|
||||||
Icons.login,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
label: const Text(
|
|
||||||
'Log In',
|
|
||||||
style: TextStyle(
|
|
||||||
fontFamily: 'Fractul',
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: AppColors.accentOrange,
|
backgroundColor: AppColors.accentOrange,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -392,6 +388,38 @@ class _MenuDrawer extends ConsumerWidget {
|
|||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(15),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.login,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(top: 1),
|
||||||
|
child: Text(
|
||||||
|
'Log In',
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: 'Fractul',
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Colors.white,
|
||||||
|
height: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|||||||
Reference in New Issue
Block a user