diff --git a/assets/icons/moon.svg b/assets/icons/moon.svg
new file mode 100644
index 0000000..7757b12
--- /dev/null
+++ b/assets/icons/moon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/sun.svg b/assets/icons/sun.svg
new file mode 100644
index 0000000..bca45f7
--- /dev/null
+++ b/assets/icons/sun.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/core/config/dependencies.dart b/lib/core/config/dependencies.dart
index 53c57b9..fe6daef 100644
--- a/lib/core/config/dependencies.dart
+++ b/lib/core/config/dependencies.dart
@@ -84,8 +84,10 @@ List get viewModels {
),
ChangeNotifierProvider(
create:
- (context) =>
- TenderDetailViewModel(tenderDetailRepository: context.read()),
+ (context) => TenderDetailViewModel(
+ tenderDetailRepository: context.read(),
+ tendersRepository: context.read(),
+ ),
),
ChangeNotifierProvider(
diff --git a/lib/core/constants/assets.dart b/lib/core/constants/assets.dart
index 76b941b..02e8bcf 100644
--- a/lib/core/constants/assets.dart
+++ b/lib/core/constants/assets.dart
@@ -15,7 +15,8 @@ class AssetsManager {
static const userIcon = 'assets/svgs/user_icon.svg';
static const passwordIcon = 'assets/svgs/password_icon.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
static const tenderLogo = 'assets/icons/tenderLogo.png';
@@ -44,4 +45,8 @@ class AssetsManager {
static const tickCircle = 'assets/icons/tick-circle.svg';
static const arrowLeft = 'assets/svgs/arrow_left.svg';
static const export = 'assets/svgs/export.svg';
+
+ //profile page
+ static const sun = 'assets/icons/sun.svg';
+ static const moon = 'assets/icons/moon.svg';
}
diff --git a/lib/core/constants/strings.dart b/lib/core/constants/strings.dart
index 5bd901e..c5a735e 100644
--- a/lib/core/constants/strings.dart
+++ b/lib/core/constants/strings.dart
@@ -47,6 +47,8 @@ class AppStrings {
//profile
static const String profile = 'Profile';
+ static const String settings = 'Settings';
+ static const String appTheme = 'App Theme';
//your tenders
static const String yourTendersTitle = 'Your tenders';
diff --git a/lib/core/network/network_manager.dart b/lib/core/network/network_manager.dart
index 26b5498..c380497 100644
--- a/lib/core/network/network_manager.dart
+++ b/lib/core/network/network_manager.dart
@@ -11,6 +11,7 @@ import 'network_connectivity.dart';
class NetworkManager {
final Dio mainDio;
final NetworkConnectivity _connectivity = NetworkConnectivity();
+ bool _interceptorsAdded = false;
NetworkManager()
: mainDio = Dio(
@@ -21,9 +22,13 @@ class NetworkManager {
'Content-Type': 'application/json',
},
),
- );
+ ) {
+ _addInterceptors();
+ }
+
+ void _addInterceptors() {
+ if (_interceptorsAdded) return;
- Future addInterceptors() async {
final requestInterceptor = InterceptorsWrapper(
onRequest: (options, handler) {
appLogger.info('🌐 Request: ${options.method} ${options.path}');
@@ -47,6 +52,7 @@ class NetworkManager {
);
mainDio.interceptors.add(requestInterceptor);
+ _interceptorsAdded = true;
}
/// Enhanced makeRequest method with comprehensive error handling
@@ -71,8 +77,6 @@ class NetworkManager {
SharedPreferences prefs = await SharedPreferences.getInstance();
Dio dioInstance = mainDio;
- await addInterceptors();
-
Future makeApiCall(String token) async {
final headers =
token.isEmpty
diff --git a/lib/core/theme/colors.dart b/lib/core/theme/colors.dart
index aafb720..4407c30 100644
--- a/lib/core/theme/colors.dart
+++ b/lib/core/theme/colors.dart
@@ -137,6 +137,9 @@ class AppColors {
static Color get blue0 =>
_isDarkMode ? const Color(0xFF4C6367) : const Color(0xFFD6F4F8);
+ static Color get error =>
+ _isDarkMode ? const Color(0xFFFF3232) : const Color(0xFFC02525);
+
static Color get red0 =>
_isDarkMode
? const Color(0xFF312F2F)
diff --git a/lib/data/repositories/tenders_repository.dart b/lib/data/repositories/tenders_repository.dart
index 6d6f5bd..8d991ad 100644
--- a/lib/data/repositories/tenders_repository.dart
+++ b/lib/data/repositories/tenders_repository.dart
@@ -1,8 +1,11 @@
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/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/tenders_service.dart';
+import '../services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart';
+
class TendersRepository {
TendersRepository({required TendersService tendersService})
: _tendersService = tendersService;
@@ -30,4 +33,22 @@ class TendersRepository {
feedbackType: feedbackType,
);
}
+
+ Future> toggleApprovals({
+ required String tenderId,
+ required String submissionMode,
+ required String status,
+ }) async {
+ return _tendersService.toggleApprovals(
+ tenderId: tenderId,
+ submissionMode: submissionMode,
+ status: status,
+ );
+ }
+
+ Future> getTenderApprovals({
+ required String tenderId,
+ }) async {
+ return _tendersService.getTenderApprovalsById(tenderId: tenderId);
+ }
}
diff --git a/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart b/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart
new file mode 100644
index 0000000..6539b92
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart
@@ -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 json) =>
+ _$TenderApprovalsByIdResponseFromJson(json);
+}
diff --git a/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.freezed.dart b/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.freezed.dart
new file mode 100644
index 0000000..9b0a73a
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.freezed.dart
@@ -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 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 get copyWith => _$TenderApprovalsByIdResponseCopyWithImpl(this as TenderApprovalsByIdResponse, _$identity);
+
+ /// Serializes this TenderApprovalsByIdResponse to a JSON map.
+ Map 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 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 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? 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 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 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? 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 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 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
diff --git a/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.g.dart b/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.g.dart
new file mode 100644
index 0000000..aa48e94
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.g.dart
@@ -0,0 +1,31 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'tender_approvals_by_id_response.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_TenderApprovalsByIdResponse _$TenderApprovalsByIdResponseFromJson(
+ Map json,
+) => _TenderApprovalsByIdResponse(
+ message: json['message'] as String?,
+ success: json['success'] as bool?,
+ error:
+ json['error'] == null
+ ? null
+ : ErrorModel.fromJson(json['error'] as Map),
+ data:
+ json['data'] == null
+ ? null
+ : TenderApprovalsData.fromJson(json['data'] as Map),
+);
+
+Map _$TenderApprovalsByIdResponseToJson(
+ _TenderApprovalsByIdResponse instance,
+) => {
+ 'message': instance.message,
+ 'success': instance.success,
+ 'error': instance.error,
+ 'data': instance.data,
+};
diff --git a/lib/data/services/model/tender_approvals_data/tender_approvals_data.dart b/lib/data/services/model/tender_approvals_data/tender_approvals_data.dart
index a5141ba..b69e111 100644
--- a/lib/data/services/model/tender_approvals_data/tender_approvals_data.dart
+++ b/lib/data/services/model/tender_approvals_data/tender_approvals_data.dart
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
@@ -22,3 +23,29 @@ abstract class TenderApprovalsData with _$TenderApprovalsData {
factory TenderApprovalsData.fromJson(Map json) =>
_$TenderApprovalsDataFromJson(json);
}
+=======
+// ignore_for_file: invalid_annotation_target
+
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+import '../tender_data/tender_data.dart';
+
+part 'tender_approvals_data.freezed.dart';
+part 'tender_approvals_data.g.dart';
+
+@freezed
+abstract class TenderApprovalsData with _$TenderApprovalsData {
+ const factory TenderApprovalsData({
+ required String? id,
+ required String? status,
+ @JsonKey(name: 'tender_id') required String? tenderId,
+ @JsonKey(name: 'company_id') required String? companyId,
+ @JsonKey(name: 'submission_mode') required String? submissionMode,
+ @JsonKey(name: 'created_at') required int? createdAt,
+ required TenderData? tender,
+ }) = _TenderApprovalsData;
+
+ factory TenderApprovalsData.fromJson(Map json) =>
+ _$TenderApprovalsDataFromJson(json);
+}
+>>>>>>> tenders_approval
diff --git a/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart b/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart
index b5355b6..3e58fce 100644
--- a/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart
+++ b/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
@@ -20,3 +21,27 @@ abstract class TenderApprovalsResponse with _$TenderApprovalsResponse {
factory TenderApprovalsResponse.fromJson(Map json) =>
_$TenderApprovalsResponseFromJson(json);
}
+=======
+// 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_response.freezed.dart';
+part 'tender_approvals_response.g.dart';
+
+@freezed
+abstract class TenderApprovalsResponse with _$TenderApprovalsResponse {
+ const factory TenderApprovalsResponse({
+ required String? message,
+ required bool? success,
+ required ErrorModel? error,
+ required List? data,
+ }) = _TenderApprovalsResponse;
+
+ factory TenderApprovalsResponse.fromJson(Map json) =>
+ _$TenderApprovalsResponseFromJson(json);
+}
+>>>>>>> tenders_approval
diff --git a/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.dart b/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.dart
new file mode 100644
index 0000000..ca0ce1a
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.dart
@@ -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 json) =>
+ _$TenderApprovalsToggleDataFromJson(json);
+}
diff --git a/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.freezed.dart b/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.freezed.dart
new file mode 100644
index 0000000..c062cee
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.freezed.dart
@@ -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 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 get copyWith => _$TenderApprovalsToggleDataCopyWithImpl(this as TenderApprovalsToggleData, _$identity);
+
+ /// Serializes this TenderApprovalsToggleData to a JSON map.
+ Map 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 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 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? 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 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 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? 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 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 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
diff --git a/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.g.dart b/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.g.dart
new file mode 100644
index 0000000..2c97758
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.g.dart
@@ -0,0 +1,29 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'tender_approvals_toggle_data.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_TenderApprovalsToggleData _$TenderApprovalsToggleDataFromJson(
+ Map 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 _$TenderApprovalsToggleDataToJson(
+ _TenderApprovalsToggleData instance,
+) => {
+ 'id': instance.id,
+ 'tender_id': instance.tenderId,
+ 'company_id': instance.companyId,
+ 'submission_mode': instance.submissionMode,
+ 'status': instance.status,
+ 'created_at': instance.createdAt,
+};
diff --git a/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart b/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart
new file mode 100644
index 0000000..4209e4e
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart
@@ -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 json) =>
+ _$TenderApprovalsToggleResponseFromJson(json);
+}
diff --git a/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.freezed.dart b/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.freezed.dart
new file mode 100644
index 0000000..f5aaad8
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.freezed.dart
@@ -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 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 get copyWith => _$TenderApprovalsToggleResponseCopyWithImpl(this as TenderApprovalsToggleResponse, _$identity);
+
+ /// Serializes this TenderApprovalsToggleResponse to a JSON map.
+ Map 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 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 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? 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 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 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? 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 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 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
diff --git a/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.g.dart b/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.g.dart
new file mode 100644
index 0000000..d1de7eb
--- /dev/null
+++ b/lib/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.g.dart
@@ -0,0 +1,33 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'tender_approvals_toggle_response.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_TenderApprovalsToggleResponse _$TenderApprovalsToggleResponseFromJson(
+ Map json,
+) => _TenderApprovalsToggleResponse(
+ message: json['message'] as String?,
+ success: json['success'] as bool?,
+ error:
+ json['error'] == null
+ ? null
+ : ErrorModel.fromJson(json['error'] as Map),
+ data:
+ json['data'] == null
+ ? null
+ : TenderApprovalsToggleData.fromJson(
+ json['data'] as Map,
+ ),
+);
+
+Map _$TenderApprovalsToggleResponseToJson(
+ _TenderApprovalsToggleResponse instance,
+) => {
+ 'message': instance.message,
+ 'success': instance.success,
+ 'error': instance.error,
+ 'data': instance.data,
+};
diff --git a/lib/data/services/tenders_service.dart b/lib/data/services/tenders_service.dart
index e7110c6..709c398 100644
--- a/lib/data/services/tenders_service.dart
+++ b/lib/data/services/tenders_service.dart
@@ -2,6 +2,8 @@ import 'dart:convert';
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/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 '../../core/network/network_manager.dart';
@@ -50,4 +52,34 @@ class TendersService {
);
return result;
}
+
+ Future> 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> getTenderApprovalsById({
+ required String tenderId,
+ }) async {
+ final result = await _networkManager.makeRequest(
+ '/api/v1/tender-approvals/tender/$tenderId',
+ method: 'GET',
+ (json) => TenderApprovalsByIdResponse.fromJson(json),
+ );
+ return result;
+ }
}
diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart
index cef5472..230abd3 100644
--- a/lib/gen/assets.gen.dart
+++ b/lib/gen/assets.gen.dart
@@ -62,6 +62,9 @@ class $AssetsIconsGen {
/// File path: 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
String get notification => 'assets/icons/notification.svg';
@@ -74,6 +77,9 @@ class $AssetsIconsGen {
/// File path: 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
String get taskSquareActive => 'assets/icons/task-square_active.svg';
@@ -114,10 +120,12 @@ class $AssetsIconsGen {
like,
location,
menu,
+ moon,
notification,
profileCircle,
profileCircleActive,
shield,
+ sun,
taskSquareActive,
taskSquare,
tenderLogoPng,
diff --git a/lib/view_models/auth_view_model.dart b/lib/view_models/auth_view_model.dart
index 047e5a7..c592f06 100644
--- a/lib/view_models/auth_view_model.dart
+++ b/lib/view_models/auth_view_model.dart
@@ -74,13 +74,6 @@ class AuthViewModel with ChangeNotifier {
notifyListeners();
}
- void forceLogout() {
- _loggedInUser = null;
- usernameController.clear();
- passwordController.clear();
- notifyListeners();
-}
-
Future logout() async {
_errorMessage = null;
notifyListeners();
diff --git a/lib/view_models/profile_view_model.dart b/lib/view_models/profile_view_model.dart
index a434cdc..5776751 100644
--- a/lib/view_models/profile_view_model.dart
+++ b/lib/view_models/profile_view_model.dart
@@ -1,8 +1,6 @@
import 'package:flutter/material.dart';
-import 'package:provider/provider.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/view_models/auth_view_model.dart';
import '../core/utils/result.dart';
import '../data/repositories/profile_repository.dart';
@@ -55,30 +53,25 @@ class ProfileViewModel with ChangeNotifier {
Future localLogout() async {
await _authRepository.localLogout();
_loggedOut = true;
+ notifyListeners();
}
-Future logout(BuildContext context) async {
- _errorMessage = null;
- notifyListeners();
+ Future logout(BuildContext context) async {
+ _errorMessage = null;
+ notifyListeners();
- final result = await _authRepository.logout();
+ final result = await _authRepository.logout();
- switch (result) {
- case Ok():
- await localLogout();
- // دسترسی به AuthViewModel و ریست یوزر
- // چون با Provider کار میکنی:
- final authViewModel = Provider.of(context, listen: false);
- authViewModel.forceLogout();
- _loggedOut = true;
- break;
- case Error():
- _errorMessage = result.error.toString();
- break;
+ switch (result) {
+ case Ok():
+ localLogout();
+ break;
+ case Error():
+ _errorMessage = result.error.toString();
+ break;
+ }
+
+ _errorMessage = null;
+ notifyListeners();
}
-
- _errorMessage = null;
- notifyListeners();
-}
-
}
diff --git a/lib/view_models/tender_detail_view_model.dart b/lib/view_models/tender_detail_view_model.dart
index a591c62..61f5ed4 100644
--- a/lib/view_models/tender_detail_view_model.dart
+++ b/lib/view_models/tender_detail_view_model.dart
@@ -1,21 +1,33 @@
import 'package:flutter/material.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/tenders_repository.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 '../data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
+
class TenderDetailViewModel with ChangeNotifier {
final TenderDetailRepository _tenderDetailRepository;
+ final TendersRepository _tendersRepository;
TenderDetailViewModel({
required TenderDetailRepository tenderDetailRepository,
- }) : _tenderDetailRepository = tenderDetailRepository;
+ required TendersRepository tendersRepository,
+ }) : _tenderDetailRepository = tenderDetailRepository,
+ _tendersRepository = tendersRepository;
bool _isLoading = false;
+ bool _isSubmitApprovalLoading = false;
+ bool _isRejectApprovalLoading = false;
String? _errorMessage;
TenderData? _tenderDetail;
+ bool approvalStatus = false;
+
bool get isLoading => _isLoading;
+ bool get isSubmitApprovalLoading => _isSubmitApprovalLoading;
+ bool get isRejectApprovalLoading => _isRejectApprovalLoading;
String? get errorMessage => _errorMessage;
TenderData? get tenderDetail => _tenderDetail;
@@ -37,4 +49,56 @@ class TenderDetailViewModel with ChangeNotifier {
_isLoading = false;
notifyListeners();
}
+
+ Future 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():
+ approvalStatus = true;
+ break;
+ case Error():
+ _errorMessage = result.error.toString();
+ approvalStatus = false;
+ break;
+ }
+ _isSubmitApprovalLoading = false;
+ notifyListeners();
+ _errorMessage = null;
+ notifyListeners();
+ }
+
+ Future 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():
+ approvalStatus = true;
+ break;
+ case Error():
+ _errorMessage = result.error.toString();
+ approvalStatus = false;
+ break;
+ }
+ _isRejectApprovalLoading = false;
+ notifyListeners();
+ _errorMessage = null;
+ notifyListeners();
+ }
}
diff --git a/lib/view_models/tenders_view_model.dart b/lib/view_models/tenders_view_model.dart
index e245562..4d50b24 100644
--- a/lib/view_models/tenders_view_model.dart
+++ b/lib/view_models/tenders_view_model.dart
@@ -4,9 +4,13 @@ import 'package:flutter/material.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_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 '../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 {
final TendersRepository _tendersRepository;
@@ -23,14 +27,20 @@ class TendersViewModel with ChangeNotifier {
String? _errorMessage;
TendersResponse? _tendersResponse;
FeedbackData? _feedbackData;
+ TenderApprovalsData? _tenderApprovalData;
+ TenderApprovalsToggleData? _tenderApprovalToggleData;
bool get isLoading => _isLoading;
bool get isLoadingMore => _isLoadingMore;
String? get errorMessage => _errorMessage;
TendersResponse? get tendersResponse => _tendersResponse;
FeedbackData? get feedbackData => _feedbackData;
+ TenderApprovalsData? get tenderApprovalData => _tenderApprovalData;
+ TenderApprovalsToggleData? get tenderApprovalToggleData =>
+ _tenderApprovalToggleData;
List feedbacks = [];
+ List tenderApprovals = [];
int currentPage = 1;
int _currentOffset = 0;
@@ -53,6 +63,26 @@ class TendersViewModel with ChangeNotifier {
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 getTenders() async {
_isLoading = true;
_errorMessage = null;
@@ -72,7 +102,9 @@ class TendersViewModel with ChangeNotifier {
_hasMoreData = _tendersResponse!.data!.tenders!.length >= _pageSize;
}
if (_tendersResponse?.data?.tenders?.isNotEmpty == true) {
+ // Fetch feedback and approvals for the first tender only
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
+ getTenderApprovals(_tendersResponse!.data!.tenders!.first.id!);
}
break;
case Error():
@@ -169,6 +201,44 @@ class TendersViewModel with ChangeNotifier {
notifyListeners();
}
+ Future getTenderApprovals(String tenderId) async {
+ _errorMessage = null;
+ notifyListeners();
+
+ final result = await _tendersRepository.getTenderApprovals(
+ tenderId: tenderId,
+ );
+ switch (result) {
+ case Ok():
+ _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():
+ _errorMessage = result.error.toString();
+ break;
+ }
+ notifyListeners();
+ _errorMessage = null;
+ notifyListeners();
+ }
+
Future feedback({
required String tenderId,
required String feedbackType,
@@ -202,4 +272,50 @@ class TendersViewModel with ChangeNotifier {
_errorMessage = null;
notifyListeners();
}
+
+ Future 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():
+ _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():
+ _errorMessage = result.error.toString();
+ break;
+ }
+ notifyListeners();
+ _errorMessage = null;
+ notifyListeners();
+ }
}
diff --git a/lib/views/detail/pages/detail_desktop_page.dart b/lib/views/detail/pages/detail_desktop_page.dart
index 453f858..7a2c7c0 100644
--- a/lib/views/detail/pages/detail_desktop_page.dart
+++ b/lib/views/detail/pages/detail_desktop_page.dart
@@ -49,7 +49,7 @@ class TenderDetailDesktopPage extends StatelessWidget {
SizedBox(height: 32.0.h()),
TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()),
- TenderDetailActions(isScreenBig: true),
+ TenderDetailActions(isScreenBig: true, detail: detail),
],
),
),
diff --git a/lib/views/detail/pages/detail_mobile_page.dart b/lib/views/detail/pages/detail_mobile_page.dart
index 30c9960..e786e39 100644
--- a/lib/views/detail/pages/detail_mobile_page.dart
+++ b/lib/views/detail/pages/detail_mobile_page.dart
@@ -45,7 +45,7 @@ class TenderDetailMobilePage extends StatelessWidget {
SizedBox(height: 24.0.h()),
TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()),
- TenderDetailActions(isScreenBig: false),
+ TenderDetailActions(isScreenBig: false, detail: detail),
],
),
),
diff --git a/lib/views/detail/pages/detail_tablet_page.dart b/lib/views/detail/pages/detail_tablet_page.dart
index 91cced4..0a5f08f 100644
--- a/lib/views/detail/pages/detail_tablet_page.dart
+++ b/lib/views/detail/pages/detail_tablet_page.dart
@@ -49,7 +49,7 @@ class TenderDetailTabletPage extends StatelessWidget {
SizedBox(height: 28.0.h()),
TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()),
- TenderDetailActions(isScreenBig: true),
+ TenderDetailActions(isScreenBig: true, detail: detail),
],
),
),
diff --git a/lib/views/detail/widgets/tender_detail_action.dart b/lib/views/detail/widgets/tender_detail_action.dart
index 7cc9bc8..7e7f6af 100644
--- a/lib/views/detail/widgets/tender_detail_action.dart
+++ b/lib/views/detail/widgets/tender_detail_action.dart
@@ -1,12 +1,22 @@
import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
import 'package:tm_app/core/constants/strings.dart';
import 'package:tm_app/core/theme/colors.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/select_submission_bottom_sheet.dart';
+
+import '../../../data/services/model/tender_data/tender_data.dart';
class TenderDetailActions extends StatelessWidget {
final bool isScreenBig;
- const TenderDetailActions({required this.isScreenBig, super.key});
+ final TenderData detail;
+ const TenderDetailActions({
+ required this.isScreenBig,
+ required this.detail,
+ super.key,
+ });
@override
Widget build(BuildContext context) {
@@ -36,22 +46,69 @@ class TenderDetailActions extends StatelessWidget {
)
: Column(
children: [
- BaseButton(
- isEnabled: true,
- text: AppStrings.tenderSubmitButton,
- backgroundColor: AppColors.primary30,
- textColor: AppColors.mainBlue,
- onPressed: () {},
+ Consumer(
+ builder: (context, viewModel, child) {
+ return viewModel.isSubmitApprovalLoading
+ ? BaseButton(
+ isEnabled: true,
+ 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()),
- BaseButton(
- isEnabled: true,
- text: AppStrings.tenderRejectButton,
- borderColor: AppColors.red10,
- textColor: AppColors.red10,
- backgroundColor: AppColors.backgroundColor,
- borderWidth: 1,
- onPressed: () {},
+ Consumer(
+ builder: (context, viewModel, child) {
+ return viewModel.isRejectApprovalLoading
+ ? BaseButton(
+ isEnabled: true,
+ text: AppStrings.tenderRejectButton,
+ borderColor: AppColors.error,
+ 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()),
],
diff --git a/lib/views/home/tenders_list_item.dart b/lib/views/home/tenders_list_item.dart
index 0756a0f..e9f3d42 100644
--- a/lib/views/home/tenders_list_item.dart
+++ b/lib/views/home/tenders_list_item.dart
@@ -46,7 +46,7 @@ class TendersListItem extends StatelessWidget {
vertical: 5.0.h(),
),
decoration: BoxDecoration(
- color: AppColors.primary2,
+ color: AppColors.primary20,
borderRadius: BorderRadius.circular(4),
),
child: Row(
diff --git a/lib/views/profile/pages/m_profile_page.dart b/lib/views/profile/pages/m_profile_page.dart
index bc065ae..7f5364f 100644
--- a/lib/views/profile/pages/m_profile_page.dart
+++ b/lib/views/profile/pages/m_profile_page.dart
@@ -1,13 +1,15 @@
import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.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 '../../../core/constants/assets.dart';
import '../../../core/constants/strings.dart';
import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart';
-import '../widgets/theme_toggle.dart';
import '../widgets/title_description.dart';
class MobileProfilePage extends StatefulWidget {
@@ -88,36 +90,67 @@ class _MobileProfilePageState extends State {
description: 'Telecommunications',
),
TitleDescription(title: 'Founded', description: '2010'),
- SizedBox(height: 24.0.h()),
- // Theme Toggle
- Container(
- padding: EdgeInsets.symmetric(
- horizontal: 16.0.w(),
- vertical: 12.0.h(),
+ SizedBox(height: 32.0.h()),
+
+ Align(
+ alignment: AlignmentDirectional.centerStart,
+ child: Text(
+ 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()),
+ Divider(color: AppColors.dividerColor, thickness: 1),
+ SizedBox(height: 24.0.h()),
+ Spacer(),
InkWell(
onTap: () => viewModel.logout(context),
child: Container(
width: double.infinity,
- height: 45.0.h(),
+ height: 56.0.h(),
decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8),
- border: Border.all(color: AppColors.borderColor),
+ color: AppColors.primary20,
+ borderRadius: BorderRadius.circular(100),
),
alignment: Alignment.center,
- child: Text('Logout'),
+ child: Text(
+ 'Logout',
+ style: TextStyle(
+ fontSize: 14.0.sp(),
+ fontWeight: FontWeight.w500,
+ color: AppColors.primaryColor,
+ ),
+ ),
),
),
],
diff --git a/lib/views/profile/widgets/theme_toggle.dart b/lib/views/profile/widgets/theme_toggle.dart
index 522b84a..66f35f5 100644
--- a/lib/views/profile/widgets/theme_toggle.dart
+++ b/lib/views/profile/widgets/theme_toggle.dart
@@ -11,26 +11,12 @@ class ThemeToggle extends StatelessWidget {
Widget build(BuildContext context) {
final themeProvider = context.watch();
- return Row(
- children: [
- Icon(
- themeProvider.isDarkMode ? Icons.dark_mode : Icons.light_mode,
- color: AppColors.primaryTextColor,
- ),
- 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,
- ),
- ],
+ return Switch(
+ value: themeProvider.isDarkMode,
+ onChanged: (value) {
+ themeProvider.toggleTheme();
+ },
+ activeColor: AppColors.primaryColor,
);
}
}
diff --git a/lib/views/shared/select_submission_bottom_sheet.dart b/lib/views/shared/select_submission_bottom_sheet.dart
new file mode 100644
index 0000000..1ccb317
--- /dev/null
+++ b/lib/views/shared/select_submission_bottom_sheet.dart
@@ -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 onConfirm;
+
+ @override
+ State createState() =>
+ _SelectSubmissionBottomSheetState();
+}
+
+class _SelectSubmissionBottomSheetState
+ extends State {
+ 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,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/views/tenders/widgets/main_tenders_slider.dart b/lib/views/tenders/widgets/main_tenders_slider.dart
index cb48180..a13b439 100644
--- a/lib/views/tenders/widgets/main_tenders_slider.dart
+++ b/lib/views/tenders/widgets/main_tenders_slider.dart
@@ -40,12 +40,15 @@ class _MainTendersSliderState extends State {
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();
final previousTenderId = widget.tenders[currentPage - 2].id!;
if (!viewModel.hasFeedbackForTender(previousTenderId)) {
viewModel.getTenderFeedback(previousTenderId);
}
+ if (!viewModel.hasTenderApprovalForTender(previousTenderId)) {
+ viewModel.getTenderApprovals(previousTenderId);
+ }
}
void _goToNextPage() {
@@ -61,12 +64,15 @@ class _MainTendersSliderState extends State {
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();
final nextTenderId = widget.tenders[currentPage].id!;
if (!viewModel.hasFeedbackForTender(nextTenderId)) {
viewModel.getTenderFeedback(nextTenderId);
}
+ if (!viewModel.hasTenderApprovalForTender(nextTenderId)) {
+ viewModel.getTenderApprovals(nextTenderId);
+ }
}
@override
@@ -95,11 +101,16 @@ class _MainTendersSliderState extends State {
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();
if (!viewModel.hasFeedbackForTender(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)
if (index >= widget.tenders.length - 1 &&
@@ -154,28 +165,26 @@ class _MainTendersSliderState extends State {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
- viewModel.isLoadingMore ?
- Padding(
- padding: EdgeInsets.only(top: 4.0.h()),
- child: SizedBox(
- width: 16.0.w(),
- height: 16.0.w(),
- child: CircularProgressIndicator(
- strokeWidth: 2.0,
- color: AppColors.jellyBean,
+ viewModel.isLoadingMore
+ ? Padding(
+ padding: EdgeInsets.only(top: 4.0.h()),
+ child: SizedBox(
+ width: 16.0.w(),
+ height: 16.0.w(),
+ child: CircularProgressIndicator(
+ strokeWidth: 2.0,
+ 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,
- ),
- ),
-
-
],
);
}
diff --git a/lib/views/tenders/widgets/tender_action_buttons_row.dart b/lib/views/tenders/widgets/tender_action_buttons_row.dart
index 77b2b0a..8abadb6 100644
--- a/lib/views/tenders/widgets/tender_action_buttons_row.dart
+++ b/lib/views/tenders/widgets/tender_action_buttons_row.dart
@@ -8,6 +8,7 @@ import 'package:tm_app/view_models/tenders_view_model.dart';
import '../../../core/constants/assets.dart';
import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart';
+import '../../shared/select_submission_bottom_sheet.dart';
class TenderActionButtonsRow extends StatelessWidget {
final TenderData tender;
@@ -35,7 +36,7 @@ class TenderActionButtonsRow extends StatelessWidget {
_rejectButton(viewModel),
SizedBox(width: 32.0.w()),
//submit button
- _submitButton(viewModel),
+ _submitButton(viewModel, context),
SizedBox(width: 32.0.w()),
// Like button
_likeButton(viewModel),
@@ -46,12 +47,22 @@ class TenderActionButtonsRow extends StatelessWidget {
}
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(
message: AppStrings.reject,
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
- // viewModel.toggleReject(tender);
+ viewModel.toggleApprovals(
+ tenderId: tender.id!,
+ submissionMode: 'self-apply',
+ status: 'rejected',
+ );
},
child: Column(
children: [
@@ -61,22 +72,14 @@ class TenderActionButtonsRow extends StatelessWidget {
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
- color:
- // tender.rejected ?? false
- // ? AppColors.errorColor
- // :
- AppColors.grey60,
+ color: isRejected ? AppColors.errorColor : AppColors.grey60,
width: 1.5.w(),
),
),
alignment: Alignment.center,
child: Icon(
Icons.close,
- color:
- // tender.rejected ?? false
- // ? AppColors.errorColor
- // :
- AppColors.grey60,
+ color: isRejected ? AppColors.errorColor : AppColors.grey60,
size: 16,
),
),
@@ -87,11 +90,7 @@ class TenderActionButtonsRow extends StatelessWidget {
style: TextStyle(
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
- color:
- // tender.rejected ?? false
- // ? AppColors.errorColor
- // :
- AppColors.grey60,
+ color: isRejected ? 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(
message: AppStrings.submit,
child: InkWell(
splashColor: Colors.transparent,
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(
children: [
@@ -116,24 +143,15 @@ class TenderActionButtonsRow extends StatelessWidget {
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
- color:
- // tender.submitted ?? false
- // ? AppColors.successColor
- // :
- AppColors.grey60,
+ color: isApproved ? AppColors.successColor : AppColors.grey60,
width: 1.5.w(),
),
),
alignment: Alignment.center,
- child: SvgPicture.asset(
- AssetsManager.tick,
- colorFilter: ColorFilter.mode(
- // tender.submitted ?? false
- // ? AppColors.successColor
- // :
- AppColors.grey60,
- BlendMode.srcATop,
- ),
+ child: Icon(
+ Icons.check,
+ color: isApproved ? AppColors.successColor : AppColors.grey60,
+ size: 16,
),
),
SizedBox(height: 8.0.h()),
@@ -143,11 +161,7 @@ class TenderActionButtonsRow extends StatelessWidget {
style: TextStyle(
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
- color:
- // tender.submitted ?? false
- // ? AppColors.successColor
- // :
- AppColors.grey60,
+ color: isApproved ? AppColors.successColor : AppColors.grey60,
),
),
],
@@ -158,6 +172,8 @@ class TenderActionButtonsRow extends StatelessWidget {
Widget _dislikeButton(TendersViewModel viewModel) {
// Find feedback for this specific tender
+ if (tender.id == null) return const SizedBox.shrink();
+
final feedback = viewModel.getFeedbackForTender(tender.id!);
final isDisliked = feedback?.feedbackType == 'dislike';
@@ -198,6 +214,8 @@ class TenderActionButtonsRow extends StatelessWidget {
Widget _likeButton(TendersViewModel viewModel) {
// Find feedback for this specific tender
+ if (tender.id == null) return const SizedBox.shrink();
+
final feedback = viewModel.getFeedbackForTender(tender.id!);
final isLiked = feedback?.feedbackType == 'like';
diff --git a/lib/views/tenders/widgets/tender_card.dart b/lib/views/tenders/widgets/tender_card.dart
index a82afb3..78f8ace 100644
--- a/lib/views/tenders/widgets/tender_card.dart
+++ b/lib/views/tenders/widgets/tender_card.dart
@@ -55,6 +55,10 @@ class TenderCard extends StatelessWidget {
_deadlineBadge(),
SizedBox(height: 12.0.h()),
+ // Approval status badge
+ // _approvalStatusBadge(),
+ SizedBox(height: 12.0.h()),
+
// Title
_tenderTitle(),
SizedBox(height: 8.0.h()),
@@ -148,6 +152,59 @@ class TenderCard extends StatelessWidget {
);
}
+ // Widget _approvalStatusBadge() {
+ // return Consumer(
+ // 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() {
return Text(
tender.title ?? '',
@@ -244,14 +301,15 @@ class TenderCard extends StatelessWidget {
),
SizedBox(width: 8.0.w()),
// Country flag placeholder
- SizedBox(
- width: 32.0.w(),
- height: 21.0.h(),
- child: CountryFlag.fromCountryCode(
- tender.countryCode!,
- shape: RoundedRectangle(4),
+ if (tender.countryCode != null)
+ SizedBox(
+ width: 32.0.w(),
+ height: 21.0.h(),
+ child: CountryFlag.fromCountryCode(
+ tender.countryCode!,
+ shape: RoundedRectangle(4),
+ ),
),
- ),
],
),
);
@@ -260,7 +318,9 @@ class TenderCard extends StatelessWidget {
Widget _seeMoreButton(BuildContext context) {
return InkWell(
onTap: () {
- TenderDetailRouteData(tenderId: tender.id!).push(context);
+ if (tender.id != null) {
+ TenderDetailRouteData(tenderId: tender.id!).push(context);
+ }
},
child: Container(
width: 108.0.w(),