merge branches

This commit is contained in:
amirrezaghabeli
2025-08-20 13:11:22 +03:30
parent 1af9c0a76b
commit 4b51071aad
36 changed files with 1894 additions and 167 deletions
+4 -2
View File
@@ -84,8 +84,10 @@ List<SingleChildWidget> get viewModels {
),
ChangeNotifierProvider(
create:
(context) =>
TenderDetailViewModel(tenderDetailRepository: context.read()),
(context) => TenderDetailViewModel(
tenderDetailRepository: context.read(),
tendersRepository: context.read(),
),
),
ChangeNotifierProvider(
+6 -1
View File
@@ -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';
}
+2
View File
@@ -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';
+8 -4
View File
@@ -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<void> 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<Response> makeApiCall(String token) async {
final headers =
token.isEmpty
+3
View File
@@ -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)
@@ -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<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,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<String, Object?> 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<String, Object?> json) =>
_$TenderApprovalsDataFromJson(json);
}
>>>>>>> tenders_approval
@@ -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<String, Object?> 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<TenderApprovalsData>? data,
}) = _TenderApprovalsResponse;
factory TenderApprovalsResponse.fromJson(Map<String, Object?> json) =>
_$TenderApprovalsResponseFromJson(json);
}
>>>>>>> tenders_approval
@@ -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/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<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
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,
-7
View File
@@ -74,13 +74,6 @@ class AuthViewModel with ChangeNotifier {
notifyListeners();
}
void forceLogout() {
_loggedInUser = null;
usernameController.clear();
passwordController.clear();
notifyListeners();
}
Future<void> logout() async {
_errorMessage = null;
notifyListeners();
+16 -23
View File
@@ -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<void> localLogout() async {
await _authRepository.localLogout();
_loggedOut = true;
notifyListeners();
}
Future<void> logout(BuildContext context) async {
_errorMessage = null;
notifyListeners();
Future<void> logout(BuildContext context) async {
_errorMessage = null;
notifyListeners();
final result = await _authRepository.logout();
final result = await _authRepository.logout();
switch (result) {
case Ok<LogoutResponse>():
await localLogout();
// دسترسی به AuthViewModel و ریست یوزر
// چون با Provider کار می‌کنی:
final authViewModel = Provider.of<AuthViewModel>(context, listen: false);
authViewModel.forceLogout();
_loggedOut = true;
break;
case Error<LogoutResponse>():
_errorMessage = result.error.toString();
break;
switch (result) {
case Ok<LogoutResponse>():
localLogout();
break;
case Error<LogoutResponse>():
_errorMessage = result.error.toString();
break;
}
_errorMessage = null;
notifyListeners();
}
_errorMessage = null;
notifyListeners();
}
}
+65 -1
View File
@@ -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<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/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<FeedbackData> feedbacks = [];
List<TenderApprovalsData> 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<void> 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<TendersResponse>():
@@ -169,6 +201,44 @@ class TendersViewModel with ChangeNotifier {
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({
required String tenderId,
required String feedbackType,
@@ -202,4 +272,50 @@ class TendersViewModel with ChangeNotifier {
_errorMessage = null;
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()),
TenderDetailCard(detail: detail),
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()),
TenderDetailCard(detail: detail),
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()),
TenderDetailCard(detail: detail),
SizedBox(height: 24.0.h()),
TenderDetailActions(isScreenBig: true),
TenderDetailActions(isScreenBig: true, detail: detail),
],
),
),
@@ -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<TenderDetailViewModel>(
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<TenderDetailViewModel>(
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()),
],
+1 -1
View File
@@ -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(
+54 -21
View File
@@ -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<MobileProfilePage> {
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,
),
),
),
),
],
+6 -20
View File
@@ -11,26 +11,12 @@ class ThemeToggle extends StatelessWidget {
Widget build(BuildContext context) {
final themeProvider = context.watch<ThemeProvider>();
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,
);
}
}
@@ -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;
});
// 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 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<MainTendersSlider> {
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 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<MainTendersSlider> {
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>();
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<MainTendersSlider> {
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,
),
),
],
);
}
@@ -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';
+68 -8
View File
@@ -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<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() {
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(),