Merge pull request 'merge_branch' (#55) from merge_branch into main

Reviewed-on: https://repo.ravanertebat.com/TM/tm_app/pulls/55
This commit is contained in:
a.ghabeli
2025-08-20 13:20:04 +03:30
38 changed files with 1905 additions and 238 deletions
+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.03107 12.417C2.39107 17.567 6.76107 21.757 11.9911 21.987C15.6811 22.147 18.9811 20.427 20.9611 17.717C21.7811 16.607 21.3411 15.867 19.9711 16.117C19.3011 16.237 18.6111 16.287 17.8911 16.257C13.0011 16.057 9.00107 11.967 8.98107 7.13703C8.97107 5.83703 9.24107 4.60703 9.73107 3.48703C10.2711 2.24703 9.62107 1.65703 8.37107 2.18703C4.41107 3.85703 1.70107 7.84703 2.03107 12.417Z" stroke="#777777" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 584 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 18.5C15.5899 18.5 18.5 15.5899 18.5 12C18.5 8.41015 15.5899 5.5 12 5.5C8.41015 5.5 5.5 8.41015 5.5 12C5.5 15.5899 8.41015 18.5 12 18.5Z" stroke="#777777" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19.14 19.14L19.01 19.01M19.01 4.99L19.14 4.86L19.01 4.99ZM4.86 19.14L4.99 19.01L4.86 19.14ZM12 2.08V2V2.08ZM12 22V21.92V22ZM2.08 12H2H2.08ZM22 12H21.92H22ZM4.99 4.99L4.86 4.86L4.99 4.99Z" stroke="#777777" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 619 B

+4 -2
View File
@@ -84,8 +84,10 @@ List<SingleChildWidget> get viewModels {
), ),
ChangeNotifierProvider( ChangeNotifierProvider(
create: create:
(context) => (context) => TenderDetailViewModel(
TenderDetailViewModel(tenderDetailRepository: context.read()), tenderDetailRepository: context.read(),
tendersRepository: context.read(),
),
), ),
ChangeNotifierProvider( ChangeNotifierProvider(
+6 -1
View File
@@ -15,7 +15,8 @@ class AssetsManager {
static const userIcon = 'assets/svgs/user_icon.svg'; static const userIcon = 'assets/svgs/user_icon.svg';
static const passwordIcon = 'assets/svgs/password_icon.svg'; static const passwordIcon = 'assets/svgs/password_icon.svg';
static const passwordVisibility = 'assets/svgs/password_visibility.svg'; static const passwordVisibility = 'assets/svgs/password_visibility.svg';
static const passwordVisibilityOff = 'assets/svgs/password_visibility_off.svg'; static const passwordVisibilityOff =
'assets/svgs/password_visibility_off.svg';
// tenders page // tenders page
static const tenderLogo = 'assets/icons/tenderLogo.png'; static const tenderLogo = 'assets/icons/tenderLogo.png';
@@ -44,4 +45,8 @@ class AssetsManager {
static const tickCircle = 'assets/icons/tick-circle.svg'; static const tickCircle = 'assets/icons/tick-circle.svg';
static const arrowLeft = 'assets/svgs/arrow_left.svg'; static const arrowLeft = 'assets/svgs/arrow_left.svg';
static const export = 'assets/svgs/export.svg'; static const export = 'assets/svgs/export.svg';
//profile page
static const sun = 'assets/icons/sun.svg';
static const moon = 'assets/icons/moon.svg';
} }
+2
View File
@@ -47,6 +47,8 @@ class AppStrings {
//profile //profile
static const String profile = 'Profile'; static const String profile = 'Profile';
static const String settings = 'Settings';
static const String appTheme = 'App Theme';
//your tenders //your tenders
static const String yourTendersTitle = 'Your tenders'; static const String yourTendersTitle = 'Your tenders';
+8 -4
View File
@@ -11,6 +11,7 @@ import 'network_connectivity.dart';
class NetworkManager { class NetworkManager {
final Dio mainDio; final Dio mainDio;
final NetworkConnectivity _connectivity = NetworkConnectivity(); final NetworkConnectivity _connectivity = NetworkConnectivity();
bool _interceptorsAdded = false;
NetworkManager() NetworkManager()
: mainDio = Dio( : mainDio = Dio(
@@ -21,9 +22,13 @@ class NetworkManager {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
), ),
); ) {
_addInterceptors();
}
void _addInterceptors() {
if (_interceptorsAdded) return;
Future<void> addInterceptors() async {
final requestInterceptor = InterceptorsWrapper( final requestInterceptor = InterceptorsWrapper(
onRequest: (options, handler) { onRequest: (options, handler) {
appLogger.info('🌐 Request: ${options.method} ${options.path}'); appLogger.info('🌐 Request: ${options.method} ${options.path}');
@@ -47,6 +52,7 @@ class NetworkManager {
); );
mainDio.interceptors.add(requestInterceptor); mainDio.interceptors.add(requestInterceptor);
_interceptorsAdded = true;
} }
/// Enhanced makeRequest method with comprehensive error handling /// Enhanced makeRequest method with comprehensive error handling
@@ -71,8 +77,6 @@ class NetworkManager {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
Dio dioInstance = mainDio; Dio dioInstance = mainDio;
await addInterceptors();
Future<Response> makeApiCall(String token) async { Future<Response> makeApiCall(String token) async {
final headers = final headers =
token.isEmpty token.isEmpty
+3
View File
@@ -137,6 +137,9 @@ class AppColors {
static Color get blue0 => static Color get blue0 =>
_isDarkMode ? const Color(0xFF4C6367) : const Color(0xFFD6F4F8); _isDarkMode ? const Color(0xFF4C6367) : const Color(0xFFD6F4F8);
static Color get error =>
_isDarkMode ? const Color(0xFFFF3232) : const Color(0xFFC02525);
static Color get red0 => static Color get red0 =>
_isDarkMode _isDarkMode
? const Color(0xFF312F2F) ? const Color(0xFF312F2F)
@@ -1,8 +1,11 @@
import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart'; import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart'; import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
import 'package:tm_app/data/services/tenders_service.dart'; import 'package:tm_app/data/services/tenders_service.dart';
import '../services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart';
class TendersRepository { class TendersRepository {
TendersRepository({required TendersService tendersService}) TendersRepository({required TendersService tendersService})
: _tendersService = tendersService; : _tendersService = tendersService;
@@ -30,4 +33,22 @@ class TendersRepository {
feedbackType: feedbackType, feedbackType: feedbackType,
); );
} }
Future<Result<TenderApprovalsToggleResponse>> toggleApprovals({
required String tenderId,
required String submissionMode,
required String status,
}) async {
return _tendersService.toggleApprovals(
tenderId: tenderId,
submissionMode: submissionMode,
status: status,
);
}
Future<Result<TenderApprovalsByIdResponse>> getTenderApprovals({
required String tenderId,
}) async {
return _tendersService.getTenderApprovalsById(tenderId: tenderId);
}
} }
@@ -0,0 +1,22 @@
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
import '../error/error_model.dart';
import '../tender_approvals_data/tender_approvals_data.dart';
part 'tender_approvals_by_id_response.freezed.dart';
part 'tender_approvals_by_id_response.g.dart';
@freezed
abstract class TenderApprovalsByIdResponse with _$TenderApprovalsByIdResponse {
const factory TenderApprovalsByIdResponse({
required String? message,
required bool? success,
required ErrorModel? error,
required TenderApprovalsData? data,
}) = _TenderApprovalsByIdResponse;
factory TenderApprovalsByIdResponse.fromJson(Map<String, Object?> json) =>
_$TenderApprovalsByIdResponseFromJson(json);
}
@@ -0,0 +1,334 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'tender_approvals_by_id_response.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$TenderApprovalsByIdResponse {
String? get message; bool? get success; ErrorModel? get error; TenderApprovalsData? get data;
/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$TenderApprovalsByIdResponseCopyWith<TenderApprovalsByIdResponse> get copyWith => _$TenderApprovalsByIdResponseCopyWithImpl<TenderApprovalsByIdResponse>(this as TenderApprovalsByIdResponse, _$identity);
/// Serializes this TenderApprovalsByIdResponse to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsByIdResponse&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&(identical(other.data, data) || other.data == data));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,message,success,error,data);
@override
String toString() {
return 'TenderApprovalsByIdResponse(message: $message, success: $success, error: $error, data: $data)';
}
}
/// @nodoc
abstract mixin class $TenderApprovalsByIdResponseCopyWith<$Res> {
factory $TenderApprovalsByIdResponseCopyWith(TenderApprovalsByIdResponse value, $Res Function(TenderApprovalsByIdResponse) _then) = _$TenderApprovalsByIdResponseCopyWithImpl;
@useResult
$Res call({
String? message, bool? success, ErrorModel? error, TenderApprovalsData? data
});
$ErrorModelCopyWith<$Res>? get error;$TenderApprovalsDataCopyWith<$Res>? get data;
}
/// @nodoc
class _$TenderApprovalsByIdResponseCopyWithImpl<$Res>
implements $TenderApprovalsByIdResponseCopyWith<$Res> {
_$TenderApprovalsByIdResponseCopyWithImpl(this._self, this._then);
final TenderApprovalsByIdResponse _self;
final $Res Function(TenderApprovalsByIdResponse) _then;
/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? message = freezed,Object? success = freezed,Object? error = freezed,Object? data = freezed,}) {
return _then(_self.copyWith(
message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as TenderApprovalsData?,
));
}
/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ErrorModelCopyWith<$Res>? get error {
if (_self.error == null) {
return null;
}
return $ErrorModelCopyWith<$Res>(_self.error!, (value) {
return _then(_self.copyWith(error: value));
});
}/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$TenderApprovalsDataCopyWith<$Res>? get data {
if (_self.data == null) {
return null;
}
return $TenderApprovalsDataCopyWith<$Res>(_self.data!, (value) {
return _then(_self.copyWith(data: value));
});
}
}
/// Adds pattern-matching-related methods to [TenderApprovalsByIdResponse].
extension TenderApprovalsByIdResponsePatterns on TenderApprovalsByIdResponse {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _TenderApprovalsByIdResponse value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _TenderApprovalsByIdResponse() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _TenderApprovalsByIdResponse value) $default,){
final _that = this;
switch (_that) {
case _TenderApprovalsByIdResponse():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _TenderApprovalsByIdResponse value)? $default,){
final _that = this;
switch (_that) {
case _TenderApprovalsByIdResponse() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? message, bool? success, ErrorModel? error, TenderApprovalsData? data)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _TenderApprovalsByIdResponse() when $default != null:
return $default(_that.message,_that.success,_that.error,_that.data);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? message, bool? success, ErrorModel? error, TenderApprovalsData? data) $default,) {final _that = this;
switch (_that) {
case _TenderApprovalsByIdResponse():
return $default(_that.message,_that.success,_that.error,_that.data);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? message, bool? success, ErrorModel? error, TenderApprovalsData? data)? $default,) {final _that = this;
switch (_that) {
case _TenderApprovalsByIdResponse() when $default != null:
return $default(_that.message,_that.success,_that.error,_that.data);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _TenderApprovalsByIdResponse implements TenderApprovalsByIdResponse {
const _TenderApprovalsByIdResponse({required this.message, required this.success, required this.error, required this.data});
factory _TenderApprovalsByIdResponse.fromJson(Map<String, dynamic> json) => _$TenderApprovalsByIdResponseFromJson(json);
@override final String? message;
@override final bool? success;
@override final ErrorModel? error;
@override final TenderApprovalsData? data;
/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$TenderApprovalsByIdResponseCopyWith<_TenderApprovalsByIdResponse> get copyWith => __$TenderApprovalsByIdResponseCopyWithImpl<_TenderApprovalsByIdResponse>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$TenderApprovalsByIdResponseToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsByIdResponse&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&(identical(other.data, data) || other.data == data));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,message,success,error,data);
@override
String toString() {
return 'TenderApprovalsByIdResponse(message: $message, success: $success, error: $error, data: $data)';
}
}
/// @nodoc
abstract mixin class _$TenderApprovalsByIdResponseCopyWith<$Res> implements $TenderApprovalsByIdResponseCopyWith<$Res> {
factory _$TenderApprovalsByIdResponseCopyWith(_TenderApprovalsByIdResponse value, $Res Function(_TenderApprovalsByIdResponse) _then) = __$TenderApprovalsByIdResponseCopyWithImpl;
@override @useResult
$Res call({
String? message, bool? success, ErrorModel? error, TenderApprovalsData? data
});
@override $ErrorModelCopyWith<$Res>? get error;@override $TenderApprovalsDataCopyWith<$Res>? get data;
}
/// @nodoc
class __$TenderApprovalsByIdResponseCopyWithImpl<$Res>
implements _$TenderApprovalsByIdResponseCopyWith<$Res> {
__$TenderApprovalsByIdResponseCopyWithImpl(this._self, this._then);
final _TenderApprovalsByIdResponse _self;
final $Res Function(_TenderApprovalsByIdResponse) _then;
/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? message = freezed,Object? success = freezed,Object? error = freezed,Object? data = freezed,}) {
return _then(_TenderApprovalsByIdResponse(
message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as TenderApprovalsData?,
));
}
/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ErrorModelCopyWith<$Res>? get error {
if (_self.error == null) {
return null;
}
return $ErrorModelCopyWith<$Res>(_self.error!, (value) {
return _then(_self.copyWith(error: value));
});
}/// Create a copy of TenderApprovalsByIdResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$TenderApprovalsDataCopyWith<$Res>? get data {
if (_self.data == null) {
return null;
}
return $TenderApprovalsDataCopyWith<$Res>(_self.data!, (value) {
return _then(_self.copyWith(data: value));
});
}
}
// dart format on
@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tender_approvals_by_id_response.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_TenderApprovalsByIdResponse _$TenderApprovalsByIdResponseFromJson(
Map<String, dynamic> json,
) => _TenderApprovalsByIdResponse(
message: json['message'] as String?,
success: json['success'] as bool?,
error:
json['error'] == null
? null
: ErrorModel.fromJson(json['error'] as Map<String, dynamic>),
data:
json['data'] == null
? null
: TenderApprovalsData.fromJson(json['data'] as Map<String, dynamic>),
);
Map<String, dynamic> _$TenderApprovalsByIdResponseToJson(
_TenderApprovalsByIdResponse instance,
) => <String, dynamic>{
'message': instance.message,
'success': instance.success,
'error': instance.error,
'data': instance.data,
};
@@ -1,5 +1,3 @@
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import '../error/error_model.dart'; import '../error/error_model.dart';
@@ -11,7 +9,6 @@ part 'tender_approvals_response.g.dart';
@freezed @freezed
abstract class TenderApprovalsResponse with _$TenderApprovalsResponse { abstract class TenderApprovalsResponse with _$TenderApprovalsResponse {
const factory TenderApprovalsResponse({ const factory TenderApprovalsResponse({
required String? message,
required bool? success, required bool? success,
required ErrorModel? error, required ErrorModel? error,
required List<TenderApprovalsData>? data, required List<TenderApprovalsData>? data,
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$TenderApprovalsResponse { mixin _$TenderApprovalsResponse {
String? get message; bool? get success; ErrorModel? get error; List<TenderApprovalsData>? get data; bool? get success; ErrorModel? get error; List<TenderApprovalsData>? get data;
/// Create a copy of TenderApprovalsResponse /// Create a copy of TenderApprovalsResponse
/// 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 @@ $TenderApprovalsResponseCopyWith<TenderApprovalsResponse> get copyWith => _$Tend
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsResponse&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other.data, data)); return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsResponse&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other.data, data));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,message,success,error,const DeepCollectionEquality().hash(data)); int get hashCode => Object.hash(runtimeType,success,error,const DeepCollectionEquality().hash(data));
@override @override
String toString() { String toString() {
return 'TenderApprovalsResponse(message: $message, success: $success, error: $error, data: $data)'; return 'TenderApprovalsResponse(success: $success, error: $error, data: $data)';
} }
@@ -48,7 +48,7 @@ abstract mixin class $TenderApprovalsResponseCopyWith<$Res> {
factory $TenderApprovalsResponseCopyWith(TenderApprovalsResponse value, $Res Function(TenderApprovalsResponse) _then) = _$TenderApprovalsResponseCopyWithImpl; factory $TenderApprovalsResponseCopyWith(TenderApprovalsResponse value, $Res Function(TenderApprovalsResponse) _then) = _$TenderApprovalsResponseCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
String? message, bool? success, ErrorModel? error, List<TenderApprovalsData>? data bool? success, ErrorModel? error, List<TenderApprovalsData>? data
}); });
@@ -65,10 +65,9 @@ class _$TenderApprovalsResponseCopyWithImpl<$Res>
/// Create a copy of TenderApprovalsResponse /// Create a copy of TenderApprovalsResponse
/// 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? message = freezed,Object? success = freezed,Object? error = freezed,Object? data = freezed,}) { @pragma('vm:prefer-inline') @override $Res call({Object? success = freezed,Object? error = freezed,Object? data = freezed,}) {
return _then(_self.copyWith( return _then(_self.copyWith(
message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as List<TenderApprovalsData>?, as List<TenderApprovalsData>?,
@@ -168,10 +167,10 @@ return $default(_that);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? message, bool? success, ErrorModel? error, List<TenderApprovalsData>? data)? $default,{required TResult orElse(),}) {final _that = this; @optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool? success, ErrorModel? error, List<TenderApprovalsData>? data)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) { switch (_that) {
case _TenderApprovalsResponse() when $default != null: case _TenderApprovalsResponse() when $default != null:
return $default(_that.message,_that.success,_that.error,_that.data);case _: return $default(_that.success,_that.error,_that.data);case _:
return orElse(); return orElse();
} }
@@ -189,10 +188,10 @@ return $default(_that.message,_that.success,_that.error,_that.data);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? message, bool? success, ErrorModel? error, List<TenderApprovalsData>? data) $default,) {final _that = this; @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool? success, ErrorModel? error, List<TenderApprovalsData>? data) $default,) {final _that = this;
switch (_that) { switch (_that) {
case _TenderApprovalsResponse(): case _TenderApprovalsResponse():
return $default(_that.message,_that.success,_that.error,_that.data);case _: return $default(_that.success,_that.error,_that.data);case _:
throw StateError('Unexpected subclass'); throw StateError('Unexpected subclass');
} }
@@ -209,10 +208,10 @@ return $default(_that.message,_that.success,_that.error,_that.data);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? message, bool? success, ErrorModel? error, List<TenderApprovalsData>? data)? $default,) {final _that = this; @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool? success, ErrorModel? error, List<TenderApprovalsData>? data)? $default,) {final _that = this;
switch (_that) { switch (_that) {
case _TenderApprovalsResponse() when $default != null: case _TenderApprovalsResponse() when $default != null:
return $default(_that.message,_that.success,_that.error,_that.data);case _: return $default(_that.success,_that.error,_that.data);case _:
return null; return null;
} }
@@ -224,10 +223,9 @@ return $default(_that.message,_that.success,_that.error,_that.data);case _:
@JsonSerializable() @JsonSerializable()
class _TenderApprovalsResponse implements TenderApprovalsResponse { class _TenderApprovalsResponse implements TenderApprovalsResponse {
const _TenderApprovalsResponse({required this.message, required this.success, required this.error, required final List<TenderApprovalsData>? data}): _data = data; const _TenderApprovalsResponse({required this.success, required this.error, required final List<TenderApprovalsData>? data}): _data = data;
factory _TenderApprovalsResponse.fromJson(Map<String, dynamic> json) => _$TenderApprovalsResponseFromJson(json); factory _TenderApprovalsResponse.fromJson(Map<String, dynamic> json) => _$TenderApprovalsResponseFromJson(json);
@override final String? message;
@override final bool? success; @override final bool? success;
@override final ErrorModel? error; @override final ErrorModel? error;
final List<TenderApprovalsData>? _data; final List<TenderApprovalsData>? _data;
@@ -253,16 +251,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsResponse&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other._data, _data)); return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsResponse&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other._data, _data));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,message,success,error,const DeepCollectionEquality().hash(_data)); int get hashCode => Object.hash(runtimeType,success,error,const DeepCollectionEquality().hash(_data));
@override @override
String toString() { String toString() {
return 'TenderApprovalsResponse(message: $message, success: $success, error: $error, data: $data)'; return 'TenderApprovalsResponse(success: $success, error: $error, data: $data)';
} }
@@ -273,7 +271,7 @@ abstract mixin class _$TenderApprovalsResponseCopyWith<$Res> implements $TenderA
factory _$TenderApprovalsResponseCopyWith(_TenderApprovalsResponse value, $Res Function(_TenderApprovalsResponse) _then) = __$TenderApprovalsResponseCopyWithImpl; factory _$TenderApprovalsResponseCopyWith(_TenderApprovalsResponse value, $Res Function(_TenderApprovalsResponse) _then) = __$TenderApprovalsResponseCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
String? message, bool? success, ErrorModel? error, List<TenderApprovalsData>? data bool? success, ErrorModel? error, List<TenderApprovalsData>? data
}); });
@@ -290,10 +288,9 @@ class __$TenderApprovalsResponseCopyWithImpl<$Res>
/// Create a copy of TenderApprovalsResponse /// Create a copy of TenderApprovalsResponse
/// 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? message = freezed,Object? success = freezed,Object? error = freezed,Object? data = freezed,}) { @override @pragma('vm:prefer-inline') $Res call({Object? success = freezed,Object? error = freezed,Object? data = freezed,}) {
return _then(_TenderApprovalsResponse( return _then(_TenderApprovalsResponse(
message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable as ErrorModel?,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable
as List<TenderApprovalsData>?, as List<TenderApprovalsData>?,
@@ -9,7 +9,6 @@ part of 'tender_approvals_response.dart';
_TenderApprovalsResponse _$TenderApprovalsResponseFromJson( _TenderApprovalsResponse _$TenderApprovalsResponseFromJson(
Map<String, dynamic> json, Map<String, dynamic> json,
) => _TenderApprovalsResponse( ) => _TenderApprovalsResponse(
message: json['message'] as String?,
success: json['success'] as bool?, success: json['success'] as bool?,
error: error:
json['error'] == null json['error'] == null
@@ -24,7 +23,6 @@ _TenderApprovalsResponse _$TenderApprovalsResponseFromJson(
Map<String, dynamic> _$TenderApprovalsResponseToJson( Map<String, dynamic> _$TenderApprovalsResponseToJson(
_TenderApprovalsResponse instance, _TenderApprovalsResponse instance,
) => <String, dynamic>{ ) => <String, dynamic>{
'message': instance.message,
'success': instance.success, 'success': instance.success,
'error': instance.error, 'error': instance.error,
'data': instance.data, 'data': instance.data,
@@ -0,0 +1,21 @@
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
part 'tender_approvals_toggle_data.freezed.dart';
part 'tender_approvals_toggle_data.g.dart';
@freezed
abstract class TenderApprovalsToggleData with _$TenderApprovalsToggleData {
const factory TenderApprovalsToggleData({
required String? id,
@JsonKey(name: 'tender_id') required String? tenderId,
@JsonKey(name: 'company_id') required String? companyId,
@JsonKey(name: 'submission_mode') required String? submissionMode,
@JsonKey(name: 'status') required String? status,
@JsonKey(name: 'created_at') required int? createdAt,
}) = _TenderApprovalsToggleData;
factory TenderApprovalsToggleData.fromJson(Map<String, Object?> json) =>
_$TenderApprovalsToggleDataFromJson(json);
}
@@ -0,0 +1,292 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'tender_approvals_toggle_data.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$TenderApprovalsToggleData {
String? get id;@JsonKey(name: 'tender_id') String? get tenderId;@JsonKey(name: 'company_id') String? get companyId;@JsonKey(name: 'submission_mode') String? get submissionMode;@JsonKey(name: 'status') String? get status;@JsonKey(name: 'created_at') int? get createdAt;
/// Create a copy of TenderApprovalsToggleData
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$TenderApprovalsToggleDataCopyWith<TenderApprovalsToggleData> get copyWith => _$TenderApprovalsToggleDataCopyWithImpl<TenderApprovalsToggleData>(this as TenderApprovalsToggleData, _$identity);
/// Serializes this TenderApprovalsToggleData to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsToggleData&&(identical(other.id, id) || other.id == id)&&(identical(other.tenderId, tenderId) || other.tenderId == tenderId)&&(identical(other.companyId, companyId) || other.companyId == companyId)&&(identical(other.submissionMode, submissionMode) || other.submissionMode == submissionMode)&&(identical(other.status, status) || other.status == status)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,tenderId,companyId,submissionMode,status,createdAt);
@override
String toString() {
return 'TenderApprovalsToggleData(id: $id, tenderId: $tenderId, companyId: $companyId, submissionMode: $submissionMode, status: $status, createdAt: $createdAt)';
}
}
/// @nodoc
abstract mixin class $TenderApprovalsToggleDataCopyWith<$Res> {
factory $TenderApprovalsToggleDataCopyWith(TenderApprovalsToggleData value, $Res Function(TenderApprovalsToggleData) _then) = _$TenderApprovalsToggleDataCopyWithImpl;
@useResult
$Res call({
String? id,@JsonKey(name: 'tender_id') String? tenderId,@JsonKey(name: 'company_id') String? companyId,@JsonKey(name: 'submission_mode') String? submissionMode,@JsonKey(name: 'status') String? status,@JsonKey(name: 'created_at') int? createdAt
});
}
/// @nodoc
class _$TenderApprovalsToggleDataCopyWithImpl<$Res>
implements $TenderApprovalsToggleDataCopyWith<$Res> {
_$TenderApprovalsToggleDataCopyWithImpl(this._self, this._then);
final TenderApprovalsToggleData _self;
final $Res Function(TenderApprovalsToggleData) _then;
/// Create a copy of TenderApprovalsToggleData
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = freezed,Object? tenderId = freezed,Object? companyId = freezed,Object? submissionMode = freezed,Object? status = freezed,Object? createdAt = freezed,}) {
return _then(_self.copyWith(
id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String?,tenderId: freezed == tenderId ? _self.tenderId : tenderId // ignore: cast_nullable_to_non_nullable
as String?,companyId: freezed == companyId ? _self.companyId : companyId // ignore: cast_nullable_to_non_nullable
as String?,submissionMode: freezed == submissionMode ? _self.submissionMode : submissionMode // ignore: cast_nullable_to_non_nullable
as String?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as String?,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
/// Adds pattern-matching-related methods to [TenderApprovalsToggleData].
extension TenderApprovalsToggleDataPatterns on TenderApprovalsToggleData {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _TenderApprovalsToggleData value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _TenderApprovalsToggleData() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _TenderApprovalsToggleData value) $default,){
final _that = this;
switch (_that) {
case _TenderApprovalsToggleData():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _TenderApprovalsToggleData value)? $default,){
final _that = this;
switch (_that) {
case _TenderApprovalsToggleData() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'company_id') String? companyId, @JsonKey(name: 'submission_mode') String? submissionMode, @JsonKey(name: 'status') String? status, @JsonKey(name: 'created_at') int? createdAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _TenderApprovalsToggleData() when $default != null:
return $default(_that.id,_that.tenderId,_that.companyId,_that.submissionMode,_that.status,_that.createdAt);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'company_id') String? companyId, @JsonKey(name: 'submission_mode') String? submissionMode, @JsonKey(name: 'status') String? status, @JsonKey(name: 'created_at') int? createdAt) $default,) {final _that = this;
switch (_that) {
case _TenderApprovalsToggleData():
return $default(_that.id,_that.tenderId,_that.companyId,_that.submissionMode,_that.status,_that.createdAt);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'company_id') String? companyId, @JsonKey(name: 'submission_mode') String? submissionMode, @JsonKey(name: 'status') String? status, @JsonKey(name: 'created_at') int? createdAt)? $default,) {final _that = this;
switch (_that) {
case _TenderApprovalsToggleData() when $default != null:
return $default(_that.id,_that.tenderId,_that.companyId,_that.submissionMode,_that.status,_that.createdAt);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _TenderApprovalsToggleData implements TenderApprovalsToggleData {
const _TenderApprovalsToggleData({required this.id, @JsonKey(name: 'tender_id') required this.tenderId, @JsonKey(name: 'company_id') required this.companyId, @JsonKey(name: 'submission_mode') required this.submissionMode, @JsonKey(name: 'status') required this.status, @JsonKey(name: 'created_at') required this.createdAt});
factory _TenderApprovalsToggleData.fromJson(Map<String, dynamic> json) => _$TenderApprovalsToggleDataFromJson(json);
@override final String? id;
@override@JsonKey(name: 'tender_id') final String? tenderId;
@override@JsonKey(name: 'company_id') final String? companyId;
@override@JsonKey(name: 'submission_mode') final String? submissionMode;
@override@JsonKey(name: 'status') final String? status;
@override@JsonKey(name: 'created_at') final int? createdAt;
/// Create a copy of TenderApprovalsToggleData
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$TenderApprovalsToggleDataCopyWith<_TenderApprovalsToggleData> get copyWith => __$TenderApprovalsToggleDataCopyWithImpl<_TenderApprovalsToggleData>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$TenderApprovalsToggleDataToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsToggleData&&(identical(other.id, id) || other.id == id)&&(identical(other.tenderId, tenderId) || other.tenderId == tenderId)&&(identical(other.companyId, companyId) || other.companyId == companyId)&&(identical(other.submissionMode, submissionMode) || other.submissionMode == submissionMode)&&(identical(other.status, status) || other.status == status)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,tenderId,companyId,submissionMode,status,createdAt);
@override
String toString() {
return 'TenderApprovalsToggleData(id: $id, tenderId: $tenderId, companyId: $companyId, submissionMode: $submissionMode, status: $status, createdAt: $createdAt)';
}
}
/// @nodoc
abstract mixin class _$TenderApprovalsToggleDataCopyWith<$Res> implements $TenderApprovalsToggleDataCopyWith<$Res> {
factory _$TenderApprovalsToggleDataCopyWith(_TenderApprovalsToggleData value, $Res Function(_TenderApprovalsToggleData) _then) = __$TenderApprovalsToggleDataCopyWithImpl;
@override @useResult
$Res call({
String? id,@JsonKey(name: 'tender_id') String? tenderId,@JsonKey(name: 'company_id') String? companyId,@JsonKey(name: 'submission_mode') String? submissionMode,@JsonKey(name: 'status') String? status,@JsonKey(name: 'created_at') int? createdAt
});
}
/// @nodoc
class __$TenderApprovalsToggleDataCopyWithImpl<$Res>
implements _$TenderApprovalsToggleDataCopyWith<$Res> {
__$TenderApprovalsToggleDataCopyWithImpl(this._self, this._then);
final _TenderApprovalsToggleData _self;
final $Res Function(_TenderApprovalsToggleData) _then;
/// Create a copy of TenderApprovalsToggleData
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = freezed,Object? tenderId = freezed,Object? companyId = freezed,Object? submissionMode = freezed,Object? status = freezed,Object? createdAt = freezed,}) {
return _then(_TenderApprovalsToggleData(
id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String?,tenderId: freezed == tenderId ? _self.tenderId : tenderId // ignore: cast_nullable_to_non_nullable
as String?,companyId: freezed == companyId ? _self.companyId : companyId // ignore: cast_nullable_to_non_nullable
as String?,submissionMode: freezed == submissionMode ? _self.submissionMode : submissionMode // ignore: cast_nullable_to_non_nullable
as String?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as String?,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
// dart format on
@@ -0,0 +1,29 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tender_approvals_toggle_data.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_TenderApprovalsToggleData _$TenderApprovalsToggleDataFromJson(
Map<String, dynamic> json,
) => _TenderApprovalsToggleData(
id: json['id'] as String?,
tenderId: json['tender_id'] as String?,
companyId: json['company_id'] as String?,
submissionMode: json['submission_mode'] as String?,
status: json['status'] as String?,
createdAt: (json['created_at'] as num?)?.toInt(),
);
Map<String, dynamic> _$TenderApprovalsToggleDataToJson(
_TenderApprovalsToggleData instance,
) => <String, dynamic>{
'id': instance.id,
'tender_id': instance.tenderId,
'company_id': instance.companyId,
'submission_mode': instance.submissionMode,
'status': instance.status,
'created_at': instance.createdAt,
};
@@ -0,0 +1,21 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:tm_app/data/services/model/error/error_model.dart';
import '../tender_approvals_toggle_data/tender_approvals_toggle_data.dart';
part 'tender_approvals_toggle_response.freezed.dart';
part 'tender_approvals_toggle_response.g.dart';
@freezed
abstract class TenderApprovalsToggleResponse
with _$TenderApprovalsToggleResponse {
const factory TenderApprovalsToggleResponse({
required String? message,
required bool? success,
required ErrorModel? error,
required TenderApprovalsToggleData? data,
}) = _TenderApprovalsToggleResponse;
factory TenderApprovalsToggleResponse.fromJson(Map<String, Object?> json) =>
_$TenderApprovalsToggleResponseFromJson(json);
}
@@ -0,0 +1,334 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'tender_approvals_toggle_response.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$TenderApprovalsToggleResponse {
String? get message; bool? get success; ErrorModel? get error; TenderApprovalsToggleData? get data;
/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$TenderApprovalsToggleResponseCopyWith<TenderApprovalsToggleResponse> get copyWith => _$TenderApprovalsToggleResponseCopyWithImpl<TenderApprovalsToggleResponse>(this as TenderApprovalsToggleResponse, _$identity);
/// Serializes this TenderApprovalsToggleResponse to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsToggleResponse&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&(identical(other.data, data) || other.data == data));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,message,success,error,data);
@override
String toString() {
return 'TenderApprovalsToggleResponse(message: $message, success: $success, error: $error, data: $data)';
}
}
/// @nodoc
abstract mixin class $TenderApprovalsToggleResponseCopyWith<$Res> {
factory $TenderApprovalsToggleResponseCopyWith(TenderApprovalsToggleResponse value, $Res Function(TenderApprovalsToggleResponse) _then) = _$TenderApprovalsToggleResponseCopyWithImpl;
@useResult
$Res call({
String? message, bool? success, ErrorModel? error, TenderApprovalsToggleData? data
});
$ErrorModelCopyWith<$Res>? get error;$TenderApprovalsToggleDataCopyWith<$Res>? get data;
}
/// @nodoc
class _$TenderApprovalsToggleResponseCopyWithImpl<$Res>
implements $TenderApprovalsToggleResponseCopyWith<$Res> {
_$TenderApprovalsToggleResponseCopyWithImpl(this._self, this._then);
final TenderApprovalsToggleResponse _self;
final $Res Function(TenderApprovalsToggleResponse) _then;
/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? message = freezed,Object? success = freezed,Object? error = freezed,Object? data = freezed,}) {
return _then(_self.copyWith(
message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as TenderApprovalsToggleData?,
));
}
/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ErrorModelCopyWith<$Res>? get error {
if (_self.error == null) {
return null;
}
return $ErrorModelCopyWith<$Res>(_self.error!, (value) {
return _then(_self.copyWith(error: value));
});
}/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$TenderApprovalsToggleDataCopyWith<$Res>? get data {
if (_self.data == null) {
return null;
}
return $TenderApprovalsToggleDataCopyWith<$Res>(_self.data!, (value) {
return _then(_self.copyWith(data: value));
});
}
}
/// Adds pattern-matching-related methods to [TenderApprovalsToggleResponse].
extension TenderApprovalsToggleResponsePatterns on TenderApprovalsToggleResponse {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _TenderApprovalsToggleResponse value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _TenderApprovalsToggleResponse() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _TenderApprovalsToggleResponse value) $default,){
final _that = this;
switch (_that) {
case _TenderApprovalsToggleResponse():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _TenderApprovalsToggleResponse value)? $default,){
final _that = this;
switch (_that) {
case _TenderApprovalsToggleResponse() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? message, bool? success, ErrorModel? error, TenderApprovalsToggleData? data)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _TenderApprovalsToggleResponse() when $default != null:
return $default(_that.message,_that.success,_that.error,_that.data);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? message, bool? success, ErrorModel? error, TenderApprovalsToggleData? data) $default,) {final _that = this;
switch (_that) {
case _TenderApprovalsToggleResponse():
return $default(_that.message,_that.success,_that.error,_that.data);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? message, bool? success, ErrorModel? error, TenderApprovalsToggleData? data)? $default,) {final _that = this;
switch (_that) {
case _TenderApprovalsToggleResponse() when $default != null:
return $default(_that.message,_that.success,_that.error,_that.data);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _TenderApprovalsToggleResponse implements TenderApprovalsToggleResponse {
const _TenderApprovalsToggleResponse({required this.message, required this.success, required this.error, required this.data});
factory _TenderApprovalsToggleResponse.fromJson(Map<String, dynamic> json) => _$TenderApprovalsToggleResponseFromJson(json);
@override final String? message;
@override final bool? success;
@override final ErrorModel? error;
@override final TenderApprovalsToggleData? data;
/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$TenderApprovalsToggleResponseCopyWith<_TenderApprovalsToggleResponse> get copyWith => __$TenderApprovalsToggleResponseCopyWithImpl<_TenderApprovalsToggleResponse>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$TenderApprovalsToggleResponseToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsToggleResponse&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&(identical(other.data, data) || other.data == data));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,message,success,error,data);
@override
String toString() {
return 'TenderApprovalsToggleResponse(message: $message, success: $success, error: $error, data: $data)';
}
}
/// @nodoc
abstract mixin class _$TenderApprovalsToggleResponseCopyWith<$Res> implements $TenderApprovalsToggleResponseCopyWith<$Res> {
factory _$TenderApprovalsToggleResponseCopyWith(_TenderApprovalsToggleResponse value, $Res Function(_TenderApprovalsToggleResponse) _then) = __$TenderApprovalsToggleResponseCopyWithImpl;
@override @useResult
$Res call({
String? message, bool? success, ErrorModel? error, TenderApprovalsToggleData? data
});
@override $ErrorModelCopyWith<$Res>? get error;@override $TenderApprovalsToggleDataCopyWith<$Res>? get data;
}
/// @nodoc
class __$TenderApprovalsToggleResponseCopyWithImpl<$Res>
implements _$TenderApprovalsToggleResponseCopyWith<$Res> {
__$TenderApprovalsToggleResponseCopyWithImpl(this._self, this._then);
final _TenderApprovalsToggleResponse _self;
final $Res Function(_TenderApprovalsToggleResponse) _then;
/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? message = freezed,Object? success = freezed,Object? error = freezed,Object? data = freezed,}) {
return _then(_TenderApprovalsToggleResponse(
message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as TenderApprovalsToggleData?,
));
}
/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ErrorModelCopyWith<$Res>? get error {
if (_self.error == null) {
return null;
}
return $ErrorModelCopyWith<$Res>(_self.error!, (value) {
return _then(_self.copyWith(error: value));
});
}/// Create a copy of TenderApprovalsToggleResponse
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$TenderApprovalsToggleDataCopyWith<$Res>? get data {
if (_self.data == null) {
return null;
}
return $TenderApprovalsToggleDataCopyWith<$Res>(_self.data!, (value) {
return _then(_self.copyWith(data: value));
});
}
}
// dart format on
@@ -0,0 +1,33 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tender_approvals_toggle_response.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_TenderApprovalsToggleResponse _$TenderApprovalsToggleResponseFromJson(
Map<String, dynamic> json,
) => _TenderApprovalsToggleResponse(
message: json['message'] as String?,
success: json['success'] as bool?,
error:
json['error'] == null
? null
: ErrorModel.fromJson(json['error'] as Map<String, dynamic>),
data:
json['data'] == null
? null
: TenderApprovalsToggleData.fromJson(
json['data'] as Map<String, dynamic>,
),
);
Map<String, dynamic> _$TenderApprovalsToggleResponseToJson(
_TenderApprovalsToggleResponse instance,
) => <String, dynamic>{
'message': instance.message,
'success': instance.success,
'error': instance.error,
'data': instance.data,
};
+32
View File
@@ -2,6 +2,8 @@ import 'dart:convert';
import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart'; import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart'; import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
import '../../core/network/network_manager.dart'; import '../../core/network/network_manager.dart';
@@ -50,4 +52,34 @@ class TendersService {
); );
return result; return result;
} }
Future<Result<TenderApprovalsToggleResponse>> toggleApprovals({
required String tenderId,
required String submissionMode,
required String status,
}) async {
final data = jsonEncode({
'tender_id': tenderId,
'submission_mode': submissionMode,
'status': status,
});
final result = await _networkManager.makeRequest(
'/api/v1/tender-approvals',
method: 'POST',
(json) => TenderApprovalsToggleResponse.fromJson(json),
data: data,
);
return result;
}
Future<Result<TenderApprovalsByIdResponse>> getTenderApprovalsById({
required String tenderId,
}) async {
final result = await _networkManager.makeRequest(
'/api/v1/tender-approvals/tender/$tenderId',
method: 'GET',
(json) => TenderApprovalsByIdResponse.fromJson(json),
);
return result;
}
} }
+8
View File
@@ -62,6 +62,9 @@ class $AssetsIconsGen {
/// File path: assets/icons/menu.svg /// File path: assets/icons/menu.svg
String get menu => 'assets/icons/menu.svg'; String get menu => 'assets/icons/menu.svg';
/// File path: assets/icons/moon.svg
String get moon => 'assets/icons/moon.svg';
/// File path: assets/icons/notification.svg /// File path: assets/icons/notification.svg
String get notification => 'assets/icons/notification.svg'; String get notification => 'assets/icons/notification.svg';
@@ -74,6 +77,9 @@ class $AssetsIconsGen {
/// File path: assets/icons/shield.svg /// File path: assets/icons/shield.svg
String get shield => 'assets/icons/shield.svg'; String get shield => 'assets/icons/shield.svg';
/// File path: assets/icons/sun.svg
String get sun => 'assets/icons/sun.svg';
/// File path: assets/icons/task-square_active.svg /// File path: assets/icons/task-square_active.svg
String get taskSquareActive => 'assets/icons/task-square_active.svg'; String get taskSquareActive => 'assets/icons/task-square_active.svg';
@@ -114,10 +120,12 @@ class $AssetsIconsGen {
like, like,
location, location,
menu, menu,
moon,
notification, notification,
profileCircle, profileCircle,
profileCircleActive, profileCircleActive,
shield, shield,
sun,
taskSquareActive, taskSquareActive,
taskSquare, taskSquare,
tenderLogoPng, tenderLogoPng,
-7
View File
@@ -74,13 +74,6 @@ class AuthViewModel with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void forceLogout() {
_loggedInUser = null;
usernameController.clear();
passwordController.clear();
notifyListeners();
}
Future<void> logout() async { Future<void> logout() async {
_errorMessage = null; _errorMessage = null;
notifyListeners(); notifyListeners();
+16 -23
View File
@@ -1,8 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/data/repositories/auth_repository.dart'; import 'package:tm_app/data/repositories/auth_repository.dart';
import 'package:tm_app/data/services/model/profile_data/profile_data.dart'; import 'package:tm_app/data/services/model/profile_data/profile_data.dart';
import 'package:tm_app/view_models/auth_view_model.dart';
import '../core/utils/result.dart'; import '../core/utils/result.dart';
import '../data/repositories/profile_repository.dart'; import '../data/repositories/profile_repository.dart';
@@ -55,30 +53,25 @@ class ProfileViewModel with ChangeNotifier {
Future<void> localLogout() async { Future<void> localLogout() async {
await _authRepository.localLogout(); await _authRepository.localLogout();
_loggedOut = true; _loggedOut = true;
notifyListeners();
} }
Future<void> logout(BuildContext context) async { Future<void> logout(BuildContext context) async {
_errorMessage = null; _errorMessage = null;
notifyListeners(); notifyListeners();
final result = await _authRepository.logout(); final result = await _authRepository.logout();
switch (result) { switch (result) {
case Ok<LogoutResponse>(): case Ok<LogoutResponse>():
await localLogout(); localLogout();
// دسترسی به AuthViewModel و ریست یوزر break;
// چون با Provider کار می‌کنی: case Error<LogoutResponse>():
final authViewModel = Provider.of<AuthViewModel>(context, listen: false); _errorMessage = result.error.toString();
authViewModel.forceLogout(); break;
_loggedOut = true; }
break;
case Error<LogoutResponse>(): _errorMessage = null;
_errorMessage = result.error.toString(); notifyListeners();
break;
} }
_errorMessage = null;
notifyListeners();
}
} }
+65 -1
View File
@@ -1,21 +1,33 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/repositories/tender_detail_repository.dart'; import 'package:tm_app/data/repositories/tender_detail_repository.dart';
import 'package:tm_app/data/repositories/tenders_repository.dart';
import 'package:tm_app/data/services/model/tender_data/tender_data.dart'; import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
import 'package:tm_app/data/services/model/tender_detail_response/tender_detail_response_model.dart'; import 'package:tm_app/data/services/model/tender_detail_response/tender_detail_response_model.dart';
import '../data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
class TenderDetailViewModel with ChangeNotifier { class TenderDetailViewModel with ChangeNotifier {
final TenderDetailRepository _tenderDetailRepository; final TenderDetailRepository _tenderDetailRepository;
final TendersRepository _tendersRepository;
TenderDetailViewModel({ TenderDetailViewModel({
required TenderDetailRepository tenderDetailRepository, required TenderDetailRepository tenderDetailRepository,
}) : _tenderDetailRepository = tenderDetailRepository; required TendersRepository tendersRepository,
}) : _tenderDetailRepository = tenderDetailRepository,
_tendersRepository = tendersRepository;
bool _isLoading = false; bool _isLoading = false;
bool _isSubmitApprovalLoading = false;
bool _isRejectApprovalLoading = false;
String? _errorMessage; String? _errorMessage;
TenderData? _tenderDetail; TenderData? _tenderDetail;
bool approvalStatus = false;
bool get isLoading => _isLoading; bool get isLoading => _isLoading;
bool get isSubmitApprovalLoading => _isSubmitApprovalLoading;
bool get isRejectApprovalLoading => _isRejectApprovalLoading;
String? get errorMessage => _errorMessage; String? get errorMessage => _errorMessage;
TenderData? get tenderDetail => _tenderDetail; TenderData? get tenderDetail => _tenderDetail;
@@ -37,4 +49,56 @@ class TenderDetailViewModel with ChangeNotifier {
_isLoading = false; _isLoading = false;
notifyListeners(); notifyListeners();
} }
Future<void> submitTenderApproval({
required String tenderId,
required String submissionMode,
}) async {
_isSubmitApprovalLoading = true;
notifyListeners();
final result = await _tendersRepository.toggleApprovals(
tenderId: tenderId,
status: 'approved',
submissionMode: submissionMode,
);
switch (result) {
case Ok<TenderApprovalsToggleResponse>():
approvalStatus = true;
break;
case Error<TenderApprovalsToggleResponse>():
_errorMessage = result.error.toString();
approvalStatus = false;
break;
}
_isSubmitApprovalLoading = false;
notifyListeners();
_errorMessage = null;
notifyListeners();
}
Future<void> rejectTenderApproval({
required String tenderId,
required String submissionMode,
}) async {
_isRejectApprovalLoading = true;
notifyListeners();
final result = await _tendersRepository.toggleApprovals(
tenderId: tenderId,
status: 'rejected',
submissionMode: submissionMode,
);
switch (result) {
case Ok<TenderApprovalsToggleResponse>():
approvalStatus = true;
break;
case Error<TenderApprovalsToggleResponse>():
_errorMessage = result.error.toString();
approvalStatus = false;
break;
}
_isRejectApprovalLoading = false;
notifyListeners();
_errorMessage = null;
notifyListeners();
}
} }
+116
View File
@@ -4,9 +4,13 @@ import 'package:flutter/material.dart';
import 'package:tm_app/data/repositories/tenders_repository.dart'; import 'package:tm_app/data/repositories/tenders_repository.dart';
import 'package:tm_app/data/services/model/feedback_data/feedback_data.dart'; import 'package:tm_app/data/services/model/feedback_data/feedback_data.dart';
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart'; import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart'; import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
import '../core/utils/result.dart'; import '../core/utils/result.dart';
import '../data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart';
import '../data/services/model/tender_approvals_data/tender_approvals_data.dart';
class TendersViewModel with ChangeNotifier { class TendersViewModel with ChangeNotifier {
final TendersRepository _tendersRepository; final TendersRepository _tendersRepository;
@@ -23,14 +27,20 @@ class TendersViewModel with ChangeNotifier {
String? _errorMessage; String? _errorMessage;
TendersResponse? _tendersResponse; TendersResponse? _tendersResponse;
FeedbackData? _feedbackData; FeedbackData? _feedbackData;
TenderApprovalsData? _tenderApprovalData;
TenderApprovalsToggleData? _tenderApprovalToggleData;
bool get isLoading => _isLoading; bool get isLoading => _isLoading;
bool get isLoadingMore => _isLoadingMore; bool get isLoadingMore => _isLoadingMore;
String? get errorMessage => _errorMessage; String? get errorMessage => _errorMessage;
TendersResponse? get tendersResponse => _tendersResponse; TendersResponse? get tendersResponse => _tendersResponse;
FeedbackData? get feedbackData => _feedbackData; FeedbackData? get feedbackData => _feedbackData;
TenderApprovalsData? get tenderApprovalData => _tenderApprovalData;
TenderApprovalsToggleData? get tenderApprovalToggleData =>
_tenderApprovalToggleData;
List<FeedbackData> feedbacks = []; List<FeedbackData> feedbacks = [];
List<TenderApprovalsData> tenderApprovals = [];
int currentPage = 1; int currentPage = 1;
int _currentOffset = 0; int _currentOffset = 0;
@@ -53,6 +63,26 @@ class TendersViewModel with ChangeNotifier {
return feedbacks.any((f) => f.tender == tenderId); return feedbacks.any((f) => f.tender == tenderId);
} }
/// Get tender approval for a specific tender
TenderApprovalsData? getTenderApprovalForTender(String tenderId) {
try {
return tenderApprovals.firstWhere((a) => a.tenderId == tenderId);
} catch (e) {
return null;
}
}
/// Check if tender approval exists for a specific tender
bool hasTenderApprovalForTender(String tenderId) {
return tenderApprovals.any((a) => a.tenderId == tenderId);
}
/// Get approval status for a specific tender
String? getApprovalStatusForTender(String tenderId) {
final approval = getTenderApprovalForTender(tenderId);
return approval?.status;
}
Future<void> getTenders() async { Future<void> getTenders() async {
_isLoading = true; _isLoading = true;
_errorMessage = null; _errorMessage = null;
@@ -72,7 +102,9 @@ class TendersViewModel with ChangeNotifier {
_hasMoreData = _tendersResponse!.data!.tenders!.length >= _pageSize; _hasMoreData = _tendersResponse!.data!.tenders!.length >= _pageSize;
} }
if (_tendersResponse?.data?.tenders?.isNotEmpty == true) { if (_tendersResponse?.data?.tenders?.isNotEmpty == true) {
// Fetch feedback and approvals for the first tender only
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!); getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
getTenderApprovals(_tendersResponse!.data!.tenders!.first.id!);
} }
break; break;
case Error<TendersResponse>(): case Error<TendersResponse>():
@@ -169,6 +201,44 @@ class TendersViewModel with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> getTenderApprovals(String tenderId) async {
_errorMessage = null;
notifyListeners();
final result = await _tendersRepository.getTenderApprovals(
tenderId: tenderId,
);
switch (result) {
case Ok<TenderApprovalsByIdResponse>():
_tenderApprovalData = result.value.data;
// Add or update _tenderApprovalData in tenderApprovals list by tender id
if (_tenderApprovalData != null) {
final index = tenderApprovals.indexWhere(
(a) => a.tenderId == _tenderApprovalData!.tenderId,
);
if (index != -1) {
tenderApprovals[index] = _tenderApprovalData!;
log(
'Updated approval for tender: ${_tenderApprovalData!.tenderId}',
);
} else {
tenderApprovals.add(_tenderApprovalData!);
log(
'Added new approval for tender: ${_tenderApprovalData!.tenderId}',
);
}
log('Total approvals: ${tenderApprovals.length}');
}
break;
case Error<TenderApprovalsByIdResponse>():
_errorMessage = result.error.toString();
break;
}
notifyListeners();
_errorMessage = null;
notifyListeners();
}
Future<void> feedback({ Future<void> feedback({
required String tenderId, required String tenderId,
required String feedbackType, required String feedbackType,
@@ -202,4 +272,50 @@ class TendersViewModel with ChangeNotifier {
_errorMessage = null; _errorMessage = null;
notifyListeners(); notifyListeners();
} }
Future<void> toggleApprovals({
required String tenderId,
required String submissionMode,
required String status,
}) async {
_errorMessage = null;
notifyListeners();
final result = await _tendersRepository.toggleApprovals(
tenderId: tenderId,
submissionMode: submissionMode,
status: status,
);
switch (result) {
case Ok<TenderApprovalsToggleResponse>():
_tenderApprovalToggleData = result.value.data;
if (_tenderApprovalToggleData != null) {
// Convert TenderApprovalsToggleData to TenderApprovalsData
final approvalData = TenderApprovalsData(
id: _tenderApprovalToggleData!.id,
status: _tenderApprovalToggleData!.status!,
tenderId: _tenderApprovalToggleData!.tenderId,
companyId: _tenderApprovalToggleData!.companyId,
submissionMode: _tenderApprovalToggleData!.submissionMode,
createdAt: _tenderApprovalToggleData!.createdAt,
tender: null, // Tender data is not included in toggle response
);
final index = tenderApprovals.indexWhere(
(a) => a.tenderId == approvalData.tenderId,
);
if (index != -1) {
tenderApprovals[index] = approvalData;
} else {
tenderApprovals.add(approvalData);
}
}
break;
case Error<TenderApprovalsToggleResponse>():
_errorMessage = result.error.toString();
break;
}
notifyListeners();
_errorMessage = null;
notifyListeners();
}
} }
@@ -49,7 +49,7 @@ class TenderDetailDesktopPage extends StatelessWidget {
SizedBox(height: 32.0.h()), SizedBox(height: 32.0.h()),
TenderDetailCard(detail: detail), TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()), SizedBox(height: 24.0.h()),
TenderDetailActions(isScreenBig: true), TenderDetailActions(isScreenBig: true, detail: detail),
], ],
), ),
), ),
@@ -45,7 +45,7 @@ class TenderDetailMobilePage extends StatelessWidget {
SizedBox(height: 24.0.h()), SizedBox(height: 24.0.h()),
TenderDetailCard(detail: detail), TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()), SizedBox(height: 24.0.h()),
TenderDetailActions(isScreenBig: false), TenderDetailActions(isScreenBig: false, detail: detail),
], ],
), ),
), ),
@@ -49,7 +49,7 @@ class TenderDetailTabletPage extends StatelessWidget {
SizedBox(height: 28.0.h()), SizedBox(height: 28.0.h()),
TenderDetailCard(detail: detail), TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()), SizedBox(height: 24.0.h()),
TenderDetailActions(isScreenBig: true), TenderDetailActions(isScreenBig: true, detail: detail),
], ],
), ),
), ),
@@ -1,12 +1,22 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/constants/strings.dart'; import 'package:tm_app/core/constants/strings.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/tender_detail_view_model.dart';
import 'package:tm_app/views/shared/base_button.dart'; import 'package:tm_app/views/shared/base_button.dart';
import 'package:tm_app/views/shared/select_submission_bottom_sheet.dart';
import '../../../data/services/model/tender_data/tender_data.dart';
class TenderDetailActions extends StatelessWidget { class TenderDetailActions extends StatelessWidget {
final bool isScreenBig; final bool isScreenBig;
const TenderDetailActions({required this.isScreenBig, super.key}); final TenderData detail;
const TenderDetailActions({
required this.isScreenBig,
required this.detail,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -36,22 +46,69 @@ class TenderDetailActions extends StatelessWidget {
) )
: Column( : Column(
children: [ children: [
BaseButton( Consumer<TenderDetailViewModel>(
isEnabled: true, builder: (context, viewModel, child) {
text: AppStrings.tenderSubmitButton, return viewModel.isSubmitApprovalLoading
backgroundColor: AppColors.primary30, ? BaseButton(
textColor: AppColors.mainBlue, isEnabled: true,
onPressed: () {}, text: AppStrings.tenderSubmitButton,
backgroundColor: AppColors.primary30,
textColor: AppColors.mainBlue,
isLoading: true,
onPressed: () {},
)
: BaseButton(
isEnabled: true,
text: AppStrings.tenderSubmitButton,
backgroundColor: AppColors.primary30,
textColor: AppColors.mainBlue,
onPressed: () {
showModalBottomSheet(
isDismissible: true,
context: context,
builder: (context) {
return SelectSubmissionBottomSheet(
onConfirm: (value) {
viewModel.submitTenderApproval(
tenderId: detail.id!,
submissionMode: value,
);
},
);
},
);
},
);
},
), ),
SizedBox(height: 16.0.h()), SizedBox(height: 16.0.h()),
BaseButton( Consumer<TenderDetailViewModel>(
isEnabled: true, builder: (context, viewModel, child) {
text: AppStrings.tenderRejectButton, return viewModel.isRejectApprovalLoading
borderColor: AppColors.red10, ? BaseButton(
textColor: AppColors.red10, isEnabled: true,
backgroundColor: AppColors.backgroundColor, text: AppStrings.tenderRejectButton,
borderWidth: 1, borderColor: AppColors.error,
onPressed: () {}, textColor: AppColors.error,
backgroundColor: AppColors.backgroundColor,
borderWidth: 1,
onPressed: () {},
)
: BaseButton(
isEnabled: true,
text: AppStrings.tenderRejectButton,
borderColor: AppColors.error,
textColor: AppColors.error,
backgroundColor: AppColors.backgroundColor,
borderWidth: 1,
onPressed: () {
viewModel.rejectTenderApproval(
tenderId: detail.id!,
submissionMode: 'self-apply',
);
},
);
},
), ),
SizedBox(height: 16.0.h()), SizedBox(height: 16.0.h()),
], ],
+1 -1
View File
@@ -46,7 +46,7 @@ class TendersListItem extends StatelessWidget {
vertical: 5.0.h(), vertical: 5.0.h(),
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.primary2, color: AppColors.primary20,
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
), ),
child: Row( child: Row(
+54 -21
View File
@@ -1,13 +1,15 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.dart'; import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/view_models/profile_view_model.dart'; import 'package:tm_app/view_models/profile_view_model.dart';
import 'package:tm_app/views/profile/widgets/theme_toggle.dart';
import 'package:tm_app/views/shared/tender_app_bar.dart'; import 'package:tm_app/views/shared/tender_app_bar.dart';
import '../../../core/constants/assets.dart';
import '../../../core/constants/strings.dart'; import '../../../core/constants/strings.dart';
import '../../../core/theme/colors.dart'; import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
import '../widgets/theme_toggle.dart';
import '../widgets/title_description.dart'; import '../widgets/title_description.dart';
class MobileProfilePage extends StatefulWidget { class MobileProfilePage extends StatefulWidget {
@@ -88,36 +90,67 @@ class _MobileProfilePageState extends State<MobileProfilePage> {
description: 'Telecommunications', description: 'Telecommunications',
), ),
TitleDescription(title: 'Founded', description: '2010'), TitleDescription(title: 'Founded', description: '2010'),
SizedBox(height: 24.0.h()), SizedBox(height: 32.0.h()),
// Theme Toggle
Container( Align(
padding: EdgeInsets.symmetric( alignment: AlignmentDirectional.centerStart,
horizontal: 16.0.w(), child: Text(
vertical: 12.0.h(), AppStrings.settings,
style: TextStyle(
fontSize: 20.0.sp(),
fontWeight: FontWeight.w600,
color: AppColors.grey70,
),
),
),
SizedBox(height: 36.0.h()),
Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0.w()),
child: Row(
children: [
Text(
AppStrings.appTheme,
style: TextStyle(
fontSize: 16.0.sp(),
fontWeight: FontWeight.w400,
color: AppColors.grey70,
),
),
Spacer(),
SvgPicture.asset(AssetsManager.sun),
SizedBox(width: 12.0.w()),
SizedBox(
width: 52.0.w(),
height: 32.0.h(),
child: ThemeToggle(),
),
SizedBox(width: 12.0.w()),
SvgPicture.asset(AssetsManager.moon),
],
), ),
decoration: BoxDecoration(
color: AppColors.surfaceColor,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColors.borderColor),
),
child: const ThemeToggle(),
), ),
// ElevatedButton(
// onPressed: () => viewModel.logout(),
// child: const Text('Logout'),
// ),
SizedBox(height: 24.0.h()), SizedBox(height: 24.0.h()),
Divider(color: AppColors.dividerColor, thickness: 1),
SizedBox(height: 24.0.h()),
Spacer(),
InkWell( InkWell(
onTap: () => viewModel.logout(context), onTap: () => viewModel.logout(context),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
height: 45.0.h(), height: 56.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8), color: AppColors.primary20,
border: Border.all(color: AppColors.borderColor), borderRadius: BorderRadius.circular(100),
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: Text('Logout'), child: Text(
'Logout',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.primaryColor,
),
),
), ),
), ),
], ],
+6 -20
View File
@@ -11,26 +11,12 @@ class ThemeToggle extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final themeProvider = context.watch<ThemeProvider>(); final themeProvider = context.watch<ThemeProvider>();
return Row( return Switch(
children: [ value: themeProvider.isDarkMode,
Icon( onChanged: (value) {
themeProvider.isDarkMode ? Icons.dark_mode : Icons.light_mode, themeProvider.toggleTheme();
color: AppColors.primaryTextColor, },
), activeColor: AppColors.primaryColor,
const SizedBox(width: 8),
Text(
themeProvider.isDarkMode ? 'Dark Mode' : 'Light Mode',
style: TextStyle(color: AppColors.primaryTextColor, fontSize: 16),
),
const Spacer(),
Switch(
value: themeProvider.isDarkMode,
onChanged: (value) {
themeProvider.toggleTheme();
},
activeColor: AppColors.primaryColor,
),
],
); );
} }
} }
@@ -0,0 +1,145 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:tm_app/core/utils/size_config.dart';
import '../../core/theme/colors.dart';
class SelectSubmissionBottomSheet extends StatefulWidget {
const SelectSubmissionBottomSheet({required this.onConfirm, super.key});
final ValueChanged<String> onConfirm;
@override
State<SelectSubmissionBottomSheet> createState() =>
_SelectSubmissionBottomSheetState();
}
class _SelectSubmissionBottomSheetState
extends State<SelectSubmissionBottomSheet> {
int selectedType = 0;
String type = 'self-apply';
@override
Widget build(BuildContext context) {
return Wrap(
children: [
Container(
width: double.infinity,
// height: 272.0.h(),
padding: EdgeInsets.fromLTRB(24.0.w(), 24.0.h(), 24.0.w(), 33.0.h()),
decoration: BoxDecoration(
color: AppColors.backgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
),
),
child: Column(
children: [
Text(
'Select Submission',
style: TextStyle(
fontSize: 20.0.sp(),
fontWeight: FontWeight.w600,
color: AppColors.grey70,
),
),
SizedBox(height: 8.0.h()),
_submissionType(
title: 'self-apply',
isSelected: type == 'self-apply',
onTap: () {
selectedType = 0;
type = 'self-apply';
setState(() {});
},
),
SizedBox(height: 8.0.h()),
_submissionType(
title: 'Partnership',
isSelected: type == 'partnership',
onTap: () {
selectedType = 1;
type = 'partnership';
setState(() {});
},
),
SizedBox(height: 8.0.h()),
InkWell(
onTap: () {
widget.onConfirm(type);
context.pop();
},
child: Container(
width: double.infinity,
height: 56.0.h(),
decoration: BoxDecoration(
color: AppColors.primary20,
borderRadius: BorderRadius.circular(100),
),
alignment: Alignment.center,
child: Text(
'Confirm',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.mainBlue,
),
),
),
),
],
),
),
],
);
}
Widget _submissionType({
required VoidCallback onTap,
required String title,
required bool isSelected,
}) {
return InkWell(
onTap: onTap,
child: SizedBox(
width: double.infinity,
height: 56.0.h(),
child: Row(
children: [
Container(
width: 20.0.w(),
height: 20.0.w(),
margin: EdgeInsets.symmetric(
horizontal: 10.0.w(),
vertical: 10.0.h(),
),
padding: EdgeInsets.all(3),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: isSelected ? AppColors.mainBlue : AppColors.grey70,
width: 2.0,
),
),
alignment: Alignment.center,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected ? AppColors.mainBlue : Colors.transparent,
),
),
),
Text(
title,
style: TextStyle(
fontSize: 16.0.sp(),
fontWeight: FontWeight.w400,
color: AppColors.grey80,
),
),
],
),
),
);
}
}
@@ -40,12 +40,15 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
currentPage = currentPage - 1; currentPage = currentPage - 1;
}); });
// Fetch feedback for the previous tender if not already loaded // Fetch feedback and approvals for the previous tender if not already loaded
final viewModel = context.read<TendersViewModel>(); final viewModel = context.read<TendersViewModel>();
final previousTenderId = widget.tenders[currentPage - 2].id!; final previousTenderId = widget.tenders[currentPage - 2].id!;
if (!viewModel.hasFeedbackForTender(previousTenderId)) { if (!viewModel.hasFeedbackForTender(previousTenderId)) {
viewModel.getTenderFeedback(previousTenderId); viewModel.getTenderFeedback(previousTenderId);
} }
if (!viewModel.hasTenderApprovalForTender(previousTenderId)) {
viewModel.getTenderApprovals(previousTenderId);
}
} }
void _goToNextPage() { void _goToNextPage() {
@@ -61,12 +64,15 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
currentPage = currentPage + 1; currentPage = currentPage + 1;
}); });
// Fetch feedback for the next tender if not already loaded // Fetch feedback and approvals for the next tender if not already loaded
final viewModel = context.read<TendersViewModel>(); final viewModel = context.read<TendersViewModel>();
final nextTenderId = widget.tenders[currentPage].id!; final nextTenderId = widget.tenders[currentPage].id!;
if (!viewModel.hasFeedbackForTender(nextTenderId)) { if (!viewModel.hasFeedbackForTender(nextTenderId)) {
viewModel.getTenderFeedback(nextTenderId); viewModel.getTenderFeedback(nextTenderId);
} }
if (!viewModel.hasTenderApprovalForTender(nextTenderId)) {
viewModel.getTenderApprovals(nextTenderId);
}
} }
@override @override
@@ -95,11 +101,16 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
currentPage = index + 1; currentPage = index + 1;
}); });
// Fetch feedback for the new tender if not already loaded // Fetch feedback and approvals for the new tender if not already loaded
final viewModel = context.read<TendersViewModel>(); final viewModel = context.read<TendersViewModel>();
if (!viewModel.hasFeedbackForTender(widget.tenders[index].id!)) { if (!viewModel.hasFeedbackForTender(widget.tenders[index].id!)) {
viewModel.getTenderFeedback(widget.tenders[index].id!); viewModel.getTenderFeedback(widget.tenders[index].id!);
} }
if (!viewModel.hasTenderApprovalForTender(
widget.tenders[index].id!,
)) {
viewModel.getTenderApprovals(widget.tenders[index].id!);
}
// Check if we need to load more tenders (when user reaches near the end) // Check if we need to load more tenders (when user reaches near the end)
if (index >= widget.tenders.length - 1 && if (index >= widget.tenders.length - 1 &&
@@ -154,28 +165,26 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
viewModel.isLoadingMore ? viewModel.isLoadingMore
Padding( ? Padding(
padding: EdgeInsets.only(top: 4.0.h()), padding: EdgeInsets.only(top: 4.0.h()),
child: SizedBox( child: SizedBox(
width: 16.0.w(), width: 16.0.w(),
height: 16.0.w(), height: 16.0.w(),
child: CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2.0, strokeWidth: 2.0,
color: AppColors.jellyBean, color: AppColors.jellyBean,
),
),
)
: Text(
'$currentPage/${widget.tenders.length}',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey,
), ),
), ),
):
Text(
'$currentPage/${widget.tenders.length}',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey,
),
),
], ],
); );
} }
@@ -8,6 +8,7 @@ import 'package:tm_app/view_models/tenders_view_model.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/theme/colors.dart'; import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
import '../../shared/select_submission_bottom_sheet.dart';
class TenderActionButtonsRow extends StatelessWidget { class TenderActionButtonsRow extends StatelessWidget {
final TenderData tender; final TenderData tender;
@@ -35,7 +36,7 @@ class TenderActionButtonsRow extends StatelessWidget {
_rejectButton(viewModel), _rejectButton(viewModel),
SizedBox(width: 32.0.w()), SizedBox(width: 32.0.w()),
//submit button //submit button
_submitButton(viewModel), _submitButton(viewModel, context),
SizedBox(width: 32.0.w()), SizedBox(width: 32.0.w()),
// Like button // Like button
_likeButton(viewModel), _likeButton(viewModel),
@@ -46,12 +47,22 @@ class TenderActionButtonsRow extends StatelessWidget {
} }
Widget _rejectButton(TendersViewModel viewModel) { Widget _rejectButton(TendersViewModel viewModel) {
// Find approval for this specific tender
if (tender.id == null) return const SizedBox.shrink();
final approval = viewModel.getTenderApprovalForTender(tender.id!);
final isRejected = approval?.status == 'rejected';
return Tooltip( return Tooltip(
message: AppStrings.reject, message: AppStrings.reject,
child: InkWell( child: InkWell(
splashColor: Colors.transparent, splashColor: Colors.transparent,
onTap: () { onTap: () {
// viewModel.toggleReject(tender); viewModel.toggleApprovals(
tenderId: tender.id!,
submissionMode: 'self-apply',
status: 'rejected',
);
}, },
child: Column( child: Column(
children: [ children: [
@@ -61,22 +72,14 @@ class TenderActionButtonsRow extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: color: isRejected ? AppColors.errorColor : AppColors.grey60,
// tender.rejected ?? false
// ? AppColors.errorColor
// :
AppColors.grey60,
width: 1.5.w(), width: 1.5.w(),
), ),
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: Icon( child: Icon(
Icons.close, Icons.close,
color: color: isRejected ? AppColors.errorColor : AppColors.grey60,
// tender.rejected ?? false
// ? AppColors.errorColor
// :
AppColors.grey60,
size: 16, size: 16,
), ),
), ),
@@ -87,11 +90,7 @@ class TenderActionButtonsRow extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.0.sp(), fontSize: 12.0.sp(),
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: color: isRejected ? AppColors.errorColor : AppColors.grey60,
// tender.rejected ?? false
// ? AppColors.errorColor
// :
AppColors.grey60,
), ),
), ),
], ],
@@ -100,13 +99,41 @@ class TenderActionButtonsRow extends StatelessWidget {
); );
} }
Widget _submitButton(TendersViewModel viewModel) { Widget _submitButton(TendersViewModel viewModel, BuildContext context) {
// Find approval for this specific tender
if (tender.id == null) return const SizedBox.shrink();
final approval = viewModel.getTenderApprovalForTender(tender.id!);
final isApproved = approval?.status == 'approved';
return Tooltip( return Tooltip(
message: AppStrings.submit, message: AppStrings.submit,
child: InkWell( child: InkWell(
splashColor: Colors.transparent, splashColor: Colors.transparent,
onTap: () { onTap: () {
// viewModel.toggleSubmit(tender); if (isApproved) {
viewModel.toggleApprovals(
tenderId: tender.id!,
submissionMode: approval?.submissionMode ?? 'self-apply',
status: 'approved',
);
} else {
showModalBottomSheet(
isDismissible: true,
context: context,
builder: (context) {
return SelectSubmissionBottomSheet(
onConfirm: (value) {
viewModel.toggleApprovals(
tenderId: tender.id!,
submissionMode: value,
status: 'approved',
);
},
);
},
);
}
}, },
child: Column( child: Column(
children: [ children: [
@@ -116,24 +143,15 @@ class TenderActionButtonsRow extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: color: isApproved ? AppColors.successColor : AppColors.grey60,
// tender.submitted ?? false
// ? AppColors.successColor
// :
AppColors.grey60,
width: 1.5.w(), width: 1.5.w(),
), ),
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: SvgPicture.asset( child: Icon(
AssetsManager.tick, Icons.check,
colorFilter: ColorFilter.mode( color: isApproved ? AppColors.successColor : AppColors.grey60,
// tender.submitted ?? false size: 16,
// ? AppColors.successColor
// :
AppColors.grey60,
BlendMode.srcATop,
),
), ),
), ),
SizedBox(height: 8.0.h()), SizedBox(height: 8.0.h()),
@@ -143,11 +161,7 @@ class TenderActionButtonsRow extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.0.sp(), fontSize: 12.0.sp(),
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: color: isApproved ? AppColors.successColor : AppColors.grey60,
// tender.submitted ?? false
// ? AppColors.successColor
// :
AppColors.grey60,
), ),
), ),
], ],
@@ -158,6 +172,8 @@ class TenderActionButtonsRow extends StatelessWidget {
Widget _dislikeButton(TendersViewModel viewModel) { Widget _dislikeButton(TendersViewModel viewModel) {
// Find feedback for this specific tender // Find feedback for this specific tender
if (tender.id == null) return const SizedBox.shrink();
final feedback = viewModel.getFeedbackForTender(tender.id!); final feedback = viewModel.getFeedbackForTender(tender.id!);
final isDisliked = feedback?.feedbackType == 'dislike'; final isDisliked = feedback?.feedbackType == 'dislike';
@@ -198,6 +214,8 @@ class TenderActionButtonsRow extends StatelessWidget {
Widget _likeButton(TendersViewModel viewModel) { Widget _likeButton(TendersViewModel viewModel) {
// Find feedback for this specific tender // Find feedback for this specific tender
if (tender.id == null) return const SizedBox.shrink();
final feedback = viewModel.getFeedbackForTender(tender.id!); final feedback = viewModel.getFeedbackForTender(tender.id!);
final isLiked = feedback?.feedbackType == 'like'; final isLiked = feedback?.feedbackType == 'like';
+68 -8
View File
@@ -55,6 +55,10 @@ class TenderCard extends StatelessWidget {
_deadlineBadge(), _deadlineBadge(),
SizedBox(height: 12.0.h()), SizedBox(height: 12.0.h()),
// Approval status badge
// _approvalStatusBadge(),
SizedBox(height: 12.0.h()),
// Title // Title
_tenderTitle(), _tenderTitle(),
SizedBox(height: 8.0.h()), SizedBox(height: 8.0.h()),
@@ -148,6 +152,59 @@ class TenderCard extends StatelessWidget {
); );
} }
// Widget _approvalStatusBadge() {
// return Consumer<TendersViewModel>(
// builder: (context, viewModel, child) {
// final approvalStatus = viewModel.getApprovalStatusForTender(tender.id!);
// final statusText = approvalStatus ?? 'Pending';
// Color statusColor;
// switch (approvalStatus) {
// case 'approved':
// statusColor = AppColors.successColor;
// break;
// case 'rejected':
// statusColor = AppColors.errorColor;
// break;
// default:
// statusColor = AppColors.grey60;
// }
// return Container(
// width: double.infinity,
// height: 24.0.h(),
// padding: EdgeInsets.symmetric(horizontal: 8.0.w()),
// decoration: BoxDecoration(
// color: AppColors.grey20,
// borderRadius: BorderRadius.circular(4),
// border: Border.all(color: statusColor),
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text(
// 'Approval Status',
// style: TextStyle(
// color: AppColors.grey80,
// fontSize: 14.0.sp(),
// fontWeight: FontWeight.w500,
// ),
// ),
// Text(
// statusText.toUpperCase(),
// style: TextStyle(
// color: statusColor,
// fontSize: 14.0.sp(),
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// ),
// );
// },
// );
// }
Widget _tenderTitle() { Widget _tenderTitle() {
return Text( return Text(
tender.title ?? '', tender.title ?? '',
@@ -244,14 +301,15 @@ class TenderCard extends StatelessWidget {
), ),
SizedBox(width: 8.0.w()), SizedBox(width: 8.0.w()),
// Country flag placeholder // Country flag placeholder
SizedBox( if (tender.countryCode != null)
width: 32.0.w(), SizedBox(
height: 21.0.h(), width: 32.0.w(),
child: CountryFlag.fromCountryCode( height: 21.0.h(),
tender.countryCode!, child: CountryFlag.fromCountryCode(
shape: RoundedRectangle(4), tender.countryCode!,
shape: RoundedRectangle(4),
),
), ),
),
], ],
), ),
); );
@@ -260,7 +318,9 @@ class TenderCard extends StatelessWidget {
Widget _seeMoreButton(BuildContext context) { Widget _seeMoreButton(BuildContext context) {
return InkWell( return InkWell(
onTap: () { onTap: () {
TenderDetailRouteData(tenderId: tender.id!).push(context); if (tender.id != null) {
TenderDetailRouteData(tenderId: tender.id!).push(context);
}
}, },
child: Container( child: Container(
width: 108.0.w(), width: 108.0.w(),