Merge pull request 'tenders' (#48) from tenders into main
Reviewed-on: https://repo.ravanertebat.com/TM/tm_app/pulls/48
This commit is contained in:
@@ -1,8 +1,5 @@
|
|||||||
import 'package:tm_app/core/utils/result.dart';
|
import 'package:tm_app/core/utils/result.dart';
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_dislike_response/tender_dislike_response.dart';
|
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_like_response/tender_like_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_reject_response/tender_reject_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_submit_response/tender_submit_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
|
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
|
||||||
import 'package:tm_app/data/services/tenders_service.dart';
|
import 'package:tm_app/data/services/tenders_service.dart';
|
||||||
|
|
||||||
@@ -11,23 +8,26 @@ class TendersRepository {
|
|||||||
: _tendersService = tendersService;
|
: _tendersService = tendersService;
|
||||||
final TendersService _tendersService;
|
final TendersService _tendersService;
|
||||||
|
|
||||||
Future<Result<TendersResponse>> getTenders() async {
|
Future<Result<TendersResponse>> getTenders({
|
||||||
return _tendersService.getTenders();
|
required int limit,
|
||||||
|
required int offset,
|
||||||
|
}) async {
|
||||||
|
return _tendersService.getTenders(limit: limit, offset: offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Result<TenderLikeResponse>> likeTender() async {
|
Future<Result<FeedbackResponse>> getTenderFeedback({
|
||||||
return _tendersService.likeTender();
|
required String tenderId,
|
||||||
|
}) async {
|
||||||
|
return _tendersService.getTenderFeedback(tenderId: tenderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Result<TenderDislikeResponse>> dislikeTender() async {
|
Future<Result<FeedbackResponse>> feedback({
|
||||||
return _tendersService.dislikeTender();
|
required String tenderId,
|
||||||
}
|
required String feedbackType,
|
||||||
|
}) async {
|
||||||
Future<Result<TenderSubmitResponse>> submitTender() async {
|
return _tendersService.feedback(
|
||||||
return _tendersService.submitTender();
|
tenderId: tenderId,
|
||||||
}
|
feedbackType: feedbackType,
|
||||||
|
);
|
||||||
Future<Result<TenderRejectResponse>> rejectTender() async {
|
|
||||||
return _tendersService.rejectTender();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ part 'feedback_response.g.dart';
|
|||||||
abstract class FeedbackResponse with _$FeedbackResponse {
|
abstract class FeedbackResponse with _$FeedbackResponse {
|
||||||
const factory FeedbackResponse({
|
const factory FeedbackResponse({
|
||||||
@JsonKey(name: 'meta') required Meta? meta,
|
@JsonKey(name: 'meta') required Meta? meta,
|
||||||
@JsonKey(name: 'data') required List<FeedbackData>? data,
|
@JsonKey(name: 'data') required FeedbackData? data,
|
||||||
@JsonKey(name: 'error') required ErrorModel? error,
|
@JsonKey(name: 'error') required ErrorModel? error,
|
||||||
required String? message,
|
required String? message,
|
||||||
required bool? success,
|
required bool? success,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$FeedbackResponse {
|
mixin _$FeedbackResponse {
|
||||||
|
|
||||||
@JsonKey(name: 'meta') Meta? get meta;@JsonKey(name: 'data') List<FeedbackData>? get data;@JsonKey(name: 'error') ErrorModel? get error; String? get message; bool? get success;
|
@JsonKey(name: 'meta') Meta? get meta;@JsonKey(name: 'data') FeedbackData? get data;@JsonKey(name: 'error') ErrorModel? get error; String? get message; bool? get success;
|
||||||
/// Create a copy of FeedbackResponse
|
/// Create a copy of FeedbackResponse
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,12 +28,12 @@ $FeedbackResponseCopyWith<FeedbackResponse> get copyWith => _$FeedbackResponseCo
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is FeedbackResponse&&(identical(other.meta, meta) || other.meta == meta)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is FeedbackResponse&&(identical(other.meta, meta) || other.meta == meta)&&(identical(other.data, data) || other.data == data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,meta,const DeepCollectionEquality().hash(data),error,message,success);
|
int get hashCode => Object.hash(runtimeType,meta,data,error,message,success);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@@ -48,11 +48,11 @@ abstract mixin class $FeedbackResponseCopyWith<$Res> {
|
|||||||
factory $FeedbackResponseCopyWith(FeedbackResponse value, $Res Function(FeedbackResponse) _then) = _$FeedbackResponseCopyWithImpl;
|
factory $FeedbackResponseCopyWith(FeedbackResponse value, $Res Function(FeedbackResponse) _then) = _$FeedbackResponseCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
@JsonKey(name: 'meta') Meta? meta,@JsonKey(name: 'data') List<FeedbackData>? data,@JsonKey(name: 'error') ErrorModel? error, String? message, bool? success
|
@JsonKey(name: 'meta') Meta? meta,@JsonKey(name: 'data') FeedbackData? data,@JsonKey(name: 'error') ErrorModel? error, String? message, bool? success
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$MetaCopyWith<$Res>? get meta;$ErrorModelCopyWith<$Res>? get error;
|
$MetaCopyWith<$Res>? get meta;$FeedbackDataCopyWith<$Res>? get data;$ErrorModelCopyWith<$Res>? get error;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -69,7 +69,7 @@ class _$FeedbackResponseCopyWithImpl<$Res>
|
|||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
as Meta?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
as Meta?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
as List<FeedbackData>?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
as FeedbackData?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
||||||
as ErrorModel?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
as ErrorModel?,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 String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||||
as bool?,
|
as bool?,
|
||||||
@@ -91,6 +91,18 @@ $MetaCopyWith<$Res>? get meta {
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
|
$FeedbackDataCopyWith<$Res>? get data {
|
||||||
|
if (_self.data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $FeedbackDataCopyWith<$Res>(_self.data!, (value) {
|
||||||
|
return _then(_self.copyWith(data: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of FeedbackResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
$ErrorModelCopyWith<$Res>? get error {
|
$ErrorModelCopyWith<$Res>? get error {
|
||||||
if (_self.error == null) {
|
if (_self.error == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -181,7 +193,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'meta') Meta? meta, @JsonKey(name: 'data') List<FeedbackData>? data, @JsonKey(name: 'error') ErrorModel? error, String? message, bool? success)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'meta') Meta? meta, @JsonKey(name: 'data') FeedbackData? data, @JsonKey(name: 'error') ErrorModel? error, String? message, bool? success)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _FeedbackResponse() when $default != null:
|
case _FeedbackResponse() when $default != null:
|
||||||
return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);case _:
|
return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);case _:
|
||||||
@@ -202,7 +214,7 @@ return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);c
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'meta') Meta? meta, @JsonKey(name: 'data') List<FeedbackData>? data, @JsonKey(name: 'error') ErrorModel? error, String? message, bool? success) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'meta') Meta? meta, @JsonKey(name: 'data') FeedbackData? data, @JsonKey(name: 'error') ErrorModel? error, String? message, bool? success) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _FeedbackResponse():
|
case _FeedbackResponse():
|
||||||
return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);case _:
|
return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);case _:
|
||||||
@@ -222,7 +234,7 @@ return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);c
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'meta') Meta? meta, @JsonKey(name: 'data') List<FeedbackData>? data, @JsonKey(name: 'error') ErrorModel? error, String? message, bool? success)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'meta') Meta? meta, @JsonKey(name: 'data') FeedbackData? data, @JsonKey(name: 'error') ErrorModel? error, String? message, bool? success)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _FeedbackResponse() when $default != null:
|
case _FeedbackResponse() when $default != null:
|
||||||
return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);case _:
|
return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);case _:
|
||||||
@@ -237,19 +249,11 @@ return $default(_that.meta,_that.data,_that.error,_that.message,_that.success);c
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _FeedbackResponse implements FeedbackResponse {
|
class _FeedbackResponse implements FeedbackResponse {
|
||||||
const _FeedbackResponse({@JsonKey(name: 'meta') required this.meta, @JsonKey(name: 'data') required final List<FeedbackData>? data, @JsonKey(name: 'error') required this.error, required this.message, required this.success}): _data = data;
|
const _FeedbackResponse({@JsonKey(name: 'meta') required this.meta, @JsonKey(name: 'data') required this.data, @JsonKey(name: 'error') required this.error, required this.message, required this.success});
|
||||||
factory _FeedbackResponse.fromJson(Map<String, dynamic> json) => _$FeedbackResponseFromJson(json);
|
factory _FeedbackResponse.fromJson(Map<String, dynamic> json) => _$FeedbackResponseFromJson(json);
|
||||||
|
|
||||||
@override@JsonKey(name: 'meta') final Meta? meta;
|
@override@JsonKey(name: 'meta') final Meta? meta;
|
||||||
final List<FeedbackData>? _data;
|
@override@JsonKey(name: 'data') final FeedbackData? data;
|
||||||
@override@JsonKey(name: 'data') List<FeedbackData>? get data {
|
|
||||||
final value = _data;
|
|
||||||
if (value == null) return null;
|
|
||||||
if (_data is EqualUnmodifiableListView) return _data;
|
|
||||||
// ignore: implicit_dynamic_type
|
|
||||||
return EqualUnmodifiableListView(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override@JsonKey(name: 'error') final ErrorModel? error;
|
@override@JsonKey(name: 'error') final ErrorModel? error;
|
||||||
@override final String? message;
|
@override final String? message;
|
||||||
@override final bool? success;
|
@override final bool? success;
|
||||||
@@ -267,12 +271,12 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _FeedbackResponse&&(identical(other.meta, meta) || other.meta == meta)&&const DeepCollectionEquality().equals(other._data, _data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _FeedbackResponse&&(identical(other.meta, meta) || other.meta == meta)&&(identical(other.data, data) || other.data == data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,meta,const DeepCollectionEquality().hash(_data),error,message,success);
|
int get hashCode => Object.hash(runtimeType,meta,data,error,message,success);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@@ -287,11 +291,11 @@ abstract mixin class _$FeedbackResponseCopyWith<$Res> implements $FeedbackRespon
|
|||||||
factory _$FeedbackResponseCopyWith(_FeedbackResponse value, $Res Function(_FeedbackResponse) _then) = __$FeedbackResponseCopyWithImpl;
|
factory _$FeedbackResponseCopyWith(_FeedbackResponse value, $Res Function(_FeedbackResponse) _then) = __$FeedbackResponseCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
@JsonKey(name: 'meta') Meta? meta,@JsonKey(name: 'data') List<FeedbackData>? data,@JsonKey(name: 'error') ErrorModel? error, String? message, bool? success
|
@JsonKey(name: 'meta') Meta? meta,@JsonKey(name: 'data') FeedbackData? data,@JsonKey(name: 'error') ErrorModel? error, String? message, bool? success
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $MetaCopyWith<$Res>? get meta;@override $ErrorModelCopyWith<$Res>? get error;
|
@override $MetaCopyWith<$Res>? get meta;@override $FeedbackDataCopyWith<$Res>? get data;@override $ErrorModelCopyWith<$Res>? get error;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -307,8 +311,8 @@ class __$FeedbackResponseCopyWithImpl<$Res>
|
|||||||
@override @pragma('vm:prefer-inline') $Res call({Object? meta = freezed,Object? data = freezed,Object? error = freezed,Object? message = freezed,Object? success = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? meta = freezed,Object? data = freezed,Object? error = freezed,Object? message = freezed,Object? success = freezed,}) {
|
||||||
return _then(_FeedbackResponse(
|
return _then(_FeedbackResponse(
|
||||||
meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
as Meta?,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable
|
as Meta?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
as List<FeedbackData>?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
as FeedbackData?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
||||||
as ErrorModel?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
as ErrorModel?,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 String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||||
as bool?,
|
as bool?,
|
||||||
@@ -331,6 +335,18 @@ $MetaCopyWith<$Res>? get meta {
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
|
$FeedbackDataCopyWith<$Res>? get data {
|
||||||
|
if (_self.data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $FeedbackDataCopyWith<$Res>(_self.data!, (value) {
|
||||||
|
return _then(_self.copyWith(data: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of FeedbackResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
$ErrorModelCopyWith<$Res>? get error {
|
$ErrorModelCopyWith<$Res>? get error {
|
||||||
if (_self.error == null) {
|
if (_self.error == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ _FeedbackResponse _$FeedbackResponseFromJson(Map<String, dynamic> json) =>
|
|||||||
? null
|
? null
|
||||||
: Meta.fromJson(json['meta'] as Map<String, dynamic>),
|
: Meta.fromJson(json['meta'] as Map<String, dynamic>),
|
||||||
data:
|
data:
|
||||||
(json['data'] as List<dynamic>?)
|
json['data'] == null
|
||||||
?.map((e) => FeedbackData.fromJson(e as Map<String, dynamic>))
|
? null
|
||||||
.toList(),
|
: FeedbackData.fromJson(json['data'] as Map<String, dynamic>),
|
||||||
error:
|
error:
|
||||||
json['error'] == null
|
json['error'] == null
|
||||||
? null
|
? null
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'dart:convert';
|
||||||
import 'package:tm_app/core/utils/logger.dart';
|
|
||||||
import 'package:tm_app/core/utils/result.dart';
|
import 'package:tm_app/core/utils/result.dart';
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_dislike_response/tender_dislike_response.dart';
|
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_like_response/tender_like_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_reject_response/tender_reject_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tenders/tender_submit_response/tender_submit_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
|
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
|
||||||
|
|
||||||
import '../../core/network/network_manager.dart';
|
import '../../core/network/network_manager.dart';
|
||||||
@@ -14,106 +11,43 @@ class TendersService {
|
|||||||
: _networkManager = networkManager;
|
: _networkManager = networkManager;
|
||||||
final NetworkManager _networkManager;
|
final NetworkManager _networkManager;
|
||||||
|
|
||||||
Future<Result<TendersResponse>> getTenders() async {
|
Future<Result<TendersResponse>> getTenders({
|
||||||
|
required int limit,
|
||||||
|
required int offset,
|
||||||
|
}) async {
|
||||||
final result = await _networkManager.makeRequest(
|
final result = await _networkManager.makeRequest(
|
||||||
'/api/v1/tenders',
|
'/api/v1/tenders?limit=$limit&offset=$offset',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
(json) => TendersResponse.fromJson(json),
|
(json) => TendersResponse.fromJson(json),
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Result<TenderLikeResponse>> likeTender() async {
|
Future<Result<FeedbackResponse>> getTenderFeedback({
|
||||||
try {
|
required String tenderId,
|
||||||
// final result = await _networkManager.makeRequest(
|
}) async {
|
||||||
// '/api/v1/tenders',
|
final result = await _networkManager.makeRequest(
|
||||||
// (json) => TenderLikeResponse.fromJson(json),
|
'/api/v1/feedback/tender/$tenderId',
|
||||||
// method: 'POST',
|
method: 'GET',
|
||||||
// );
|
(json) => FeedbackResponse.fromJson(json),
|
||||||
// await Future.delayed(Duration(seconds: 2));
|
);
|
||||||
appLogger.info('like tender success');
|
return result;
|
||||||
// TODO: will change when api is ready
|
|
||||||
return Result.ok(
|
|
||||||
TenderLikeResponse.fromJson({'message': 'Tender liked successfully'}),
|
|
||||||
);
|
|
||||||
} on DioException catch (e) {
|
|
||||||
appLogger.error('like tender failed: $e');
|
|
||||||
return Result.error(e);
|
|
||||||
} on Exception catch (e, stackTrace) {
|
|
||||||
appLogger.error('like tender failed: $e', stackTrace: stackTrace);
|
|
||||||
return Result.error(Exception(e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Result<TenderDislikeResponse>> dislikeTender() async {
|
Future<Result<FeedbackResponse>> feedback({
|
||||||
try {
|
required String tenderId,
|
||||||
// final result = await _networkManager.makeRequest(
|
required String feedbackType,
|
||||||
// '/api/v1/tenders',
|
}) async {
|
||||||
// (json) => TenderDislikeResponse.fromJson(json),
|
final data = jsonEncode({
|
||||||
// method: 'POST',
|
'feedback_type': feedbackType,
|
||||||
// );
|
'tender_id': tenderId,
|
||||||
// await Future.delayed(Duration(seconds: 2));
|
});
|
||||||
appLogger.info('dislike tender success');
|
final result = await _networkManager.makeRequest(
|
||||||
// TODO: will change when api is ready
|
'/api/v1/feedback',
|
||||||
return Result.ok(
|
method: 'POST',
|
||||||
TenderDislikeResponse.fromJson({
|
(json) => FeedbackResponse.fromJson(json),
|
||||||
'message': 'Tender disliked successfully',
|
data: data,
|
||||||
}),
|
);
|
||||||
);
|
return result;
|
||||||
} on DioException catch (e) {
|
|
||||||
appLogger.error('dislike tender failed: $e');
|
|
||||||
return Result.error(e);
|
|
||||||
} on Exception catch (e, stackTrace) {
|
|
||||||
appLogger.error('dislike tender failed: $e', stackTrace: stackTrace);
|
|
||||||
return Result.error(Exception(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Result<TenderSubmitResponse>> submitTender() async {
|
|
||||||
try {
|
|
||||||
// final result = await _networkManager.makeRequest(
|
|
||||||
// '/api/v1/tenders',
|
|
||||||
// (json) => TenderSubmitResponse.fromJson(json),
|
|
||||||
// method: 'POST',
|
|
||||||
// );
|
|
||||||
// await Future.delayed(Duration(seconds: 2));
|
|
||||||
appLogger.info('submit tender success');
|
|
||||||
// TODO: will change when api is ready
|
|
||||||
return Result.ok(
|
|
||||||
TenderSubmitResponse.fromJson({
|
|
||||||
'message': 'Tender submitted successfully',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} on DioException catch (e) {
|
|
||||||
appLogger.error('submit tender failed: $e');
|
|
||||||
return Result.error(e);
|
|
||||||
} on Exception catch (e, stackTrace) {
|
|
||||||
appLogger.error('submit tender failed: $e', stackTrace: stackTrace);
|
|
||||||
return Result.error(Exception(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Result<TenderRejectResponse>> rejectTender() async {
|
|
||||||
try {
|
|
||||||
// final result = await _networkManager.makeRequest(
|
|
||||||
// '/api/v1/tenders',
|
|
||||||
// (json) => TenderRejectResponse.fromJson(json),
|
|
||||||
// method: 'POST',
|
|
||||||
// );
|
|
||||||
// await Future.delayed(Duration(seconds: 2));
|
|
||||||
appLogger.info('reject tender success');
|
|
||||||
// TODO: will change when api is ready
|
|
||||||
return Result.ok(
|
|
||||||
TenderRejectResponse.fromJson({
|
|
||||||
'message': 'Tender rejected successfully',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} on DioException catch (e) {
|
|
||||||
appLogger.error('reject tender failed: $e');
|
|
||||||
return Result.error(e);
|
|
||||||
} on Exception catch (e, stackTrace) {
|
|
||||||
appLogger.error('reject tender failed: $e', stackTrace: stackTrace);
|
|
||||||
return Result.error(Exception(e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tm_app/data/repositories/tenders_repository.dart';
|
import 'package:tm_app/data/repositories/tenders_repository.dart';
|
||||||
import 'package:tm_app/data/services/model/tender/tender_model.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/tenders/tenders_response/tenders_response.dart';
|
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
|
||||||
|
|
||||||
import '../core/utils/result.dart';
|
import '../core/utils/result.dart';
|
||||||
@@ -16,24 +19,61 @@ class TendersViewModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
bool _isLoadingMore = false;
|
||||||
String? _errorMessage;
|
String? _errorMessage;
|
||||||
TendersResponse? _tendersResponse;
|
TendersResponse? _tendersResponse;
|
||||||
|
FeedbackData? _feedbackData;
|
||||||
|
|
||||||
bool get isLoading => _isLoading;
|
bool get isLoading => _isLoading;
|
||||||
|
bool get isLoadingMore => _isLoadingMore;
|
||||||
String? get errorMessage => _errorMessage;
|
String? get errorMessage => _errorMessage;
|
||||||
TendersResponse? get tendersResponse => _tendersResponse;
|
TendersResponse? get tendersResponse => _tendersResponse;
|
||||||
|
FeedbackData? get feedbackData => _feedbackData;
|
||||||
|
|
||||||
|
List<FeedbackData> feedbacks = [];
|
||||||
|
|
||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
|
int _currentOffset = 0;
|
||||||
|
static const int _pageSize = 10;
|
||||||
|
bool _hasMoreData = true;
|
||||||
|
|
||||||
|
bool get hasMoreData => _hasMoreData;
|
||||||
|
|
||||||
|
/// Get feedback for a specific tender
|
||||||
|
FeedbackData? getFeedbackForTender(String tenderId) {
|
||||||
|
try {
|
||||||
|
return feedbacks.firstWhere((f) => f.tender == tenderId);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if feedback exists for a specific tender
|
||||||
|
bool hasFeedbackForTender(String tenderId) {
|
||||||
|
return feedbacks.any((f) => f.tender == tenderId);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> getTenders() async {
|
Future<void> getTenders() async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
|
_currentOffset = 0;
|
||||||
|
_hasMoreData = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
final result = await _tendersRepository.getTenders();
|
final result = await _tendersRepository.getTenders(
|
||||||
|
limit: _pageSize,
|
||||||
|
offset: _currentOffset,
|
||||||
|
);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Ok<TendersResponse>():
|
case Ok<TendersResponse>():
|
||||||
_tendersResponse = result.value;
|
_tendersResponse = result.value;
|
||||||
|
// Check if we have more data
|
||||||
|
if (_tendersResponse?.data?.tenders != null) {
|
||||||
|
_hasMoreData = _tendersResponse!.data!.tenders!.length >= _pageSize;
|
||||||
|
}
|
||||||
|
if (_tendersResponse?.data?.tenders?.isNotEmpty == true) {
|
||||||
|
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Error<TendersResponse>():
|
case Error<TendersResponse>():
|
||||||
_errorMessage = result.error.toString();
|
_errorMessage = result.error.toString();
|
||||||
@@ -45,166 +85,121 @@ class TendersViewModel with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates a tender's state in the list
|
Future<void> loadMoreTenders() async {
|
||||||
void _updateTenderState(
|
if (_isLoadingMore || !_hasMoreData) return;
|
||||||
String tenderId, {
|
|
||||||
bool? liked,
|
|
||||||
bool? disliked,
|
|
||||||
bool? rejected,
|
|
||||||
bool? submitted,
|
|
||||||
}) {
|
|
||||||
// if (_tendersResponse?.tendersData?.tenders != null) {
|
|
||||||
// final updatedTenders =
|
|
||||||
// _tendersResponse!.tendersData!.tenders!.map((element) {
|
|
||||||
// if (element.tenderId == tenderId) {
|
|
||||||
// return element.copyWith(
|
|
||||||
// liked: liked,
|
|
||||||
// disliked: disliked,
|
|
||||||
// rejected: rejected,
|
|
||||||
// submitted: submitted,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// return element;
|
|
||||||
// }).toList();
|
|
||||||
|
|
||||||
// _tendersResponse = _tendersResponse!.copyWith(
|
_isLoadingMore = true;
|
||||||
// tendersData: _tendersResponse!.tendersData!.copyWith(
|
_errorMessage = null;
|
||||||
// tenders: updatedTenders,
|
notifyListeners();
|
||||||
// ),
|
|
||||||
// );
|
_currentOffset += _pageSize;
|
||||||
// }
|
final result = await _tendersRepository.getTenders(
|
||||||
|
limit: _pageSize,
|
||||||
|
offset: _currentOffset,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case Ok<TendersResponse>():
|
||||||
|
if (result.value.data?.tenders != null &&
|
||||||
|
result.value.data!.tenders!.isNotEmpty) {
|
||||||
|
// Create a new modifiable list by combining existing and new tenders
|
||||||
|
if (_tendersResponse?.data?.tenders != null) {
|
||||||
|
final existingTenders = _tendersResponse!.data!.tenders!;
|
||||||
|
final newTenders = result.value.data!.tenders!;
|
||||||
|
final combinedTenders = [...existingTenders, ...newTenders];
|
||||||
|
|
||||||
|
// Create a new TendersData with the combined list
|
||||||
|
_tendersResponse = _tendersResponse!.copyWith(
|
||||||
|
data: _tendersResponse!.data!.copyWith(tenders: combinedTenders),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
_tendersResponse = result.value;
|
||||||
|
}
|
||||||
|
// Check if we have more data
|
||||||
|
_hasMoreData = result.value.data!.tenders!.length >= _pageSize;
|
||||||
|
} else {
|
||||||
|
_hasMoreData = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Error<TendersResponse>():
|
||||||
|
_errorMessage = result.error.toString();
|
||||||
|
_currentOffset -= _pageSize; // Revert offset on error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isLoadingMore = false;
|
||||||
|
notifyListeners();
|
||||||
|
_errorMessage = null;
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a tender as liked
|
Future<void> getTenderFeedback(String tenderId) async {
|
||||||
Future<void> markLiked(TenderModel tender) async {
|
// _isLoading = true;
|
||||||
// _updateTenderState(
|
_errorMessage = null;
|
||||||
// tender.id!,
|
notifyListeners();
|
||||||
// liked: true,
|
|
||||||
// disliked: false,
|
final result = await _tendersRepository.getTenderFeedback(
|
||||||
// rejected: false,
|
tenderId: tenderId,
|
||||||
// submitted: tender.submitted,
|
);
|
||||||
// );
|
switch (result) {
|
||||||
// notifyListeners();
|
case Ok<FeedbackResponse>():
|
||||||
// final result = await _tendersRepository.likeTender();
|
_feedbackData = result.value.data;
|
||||||
// switch (result) {
|
// Add or update _feedbackData in feedbacks list by tender id
|
||||||
// case Ok<TenderLikeResponse>():
|
if (_feedbackData != null) {
|
||||||
// break;
|
final index = feedbacks.indexWhere(
|
||||||
// case Error<TenderLikeResponse>():
|
(f) => f.tender == _feedbackData!.tender,
|
||||||
// break;
|
);
|
||||||
// }
|
if (index != -1) {
|
||||||
|
feedbacks[index] = _feedbackData!;
|
||||||
|
log('Updated feedback for tender: ${_feedbackData!.tender}');
|
||||||
|
} else {
|
||||||
|
feedbacks.add(_feedbackData!);
|
||||||
|
log('Added new feedback for tender: ${_feedbackData!.tender}');
|
||||||
|
}
|
||||||
|
log('Total feedbacks: ${feedbacks.length}');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Error<FeedbackResponse>():
|
||||||
|
_errorMessage = result.error.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// _isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
_errorMessage = null;
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a tender as disliked
|
Future<void> feedback({
|
||||||
Future<void> markDisliked(TenderModel tender) async {
|
required String tenderId,
|
||||||
// _updateTenderState(
|
required String feedbackType,
|
||||||
// tender.tenderId!,
|
}) async {
|
||||||
// disliked: true,
|
_errorMessage = null;
|
||||||
// liked: false,
|
notifyListeners();
|
||||||
// rejected: tender.rejected,
|
|
||||||
// submitted: false,
|
|
||||||
// );
|
|
||||||
// notifyListeners();
|
|
||||||
// final result = await _tendersRepository.dislikeTender();
|
|
||||||
// switch (result) {
|
|
||||||
// case Ok<TenderDislikeResponse>():
|
|
||||||
// break;
|
|
||||||
// case Error<TenderDislikeResponse>():
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets a tender as rejected
|
final result = await _tendersRepository.feedback(
|
||||||
Future<void> markRejected(TenderModel tender) async {
|
tenderId: tenderId,
|
||||||
// _updateTenderState(
|
feedbackType: feedbackType,
|
||||||
// tender.tenderId!,
|
);
|
||||||
// rejected: true,
|
switch (result) {
|
||||||
// liked: false,
|
case Ok<FeedbackResponse>():
|
||||||
// disliked: tender.disliked,
|
_feedbackData = result.value.data;
|
||||||
// submitted: false,
|
if (_feedbackData != null) {
|
||||||
// );
|
final index = feedbacks.indexWhere(
|
||||||
// notifyListeners();
|
(f) => f.tender == _feedbackData!.tender,
|
||||||
// final result = await _tendersRepository.rejectTender();
|
);
|
||||||
// switch (result) {
|
if (index != -1) {
|
||||||
// case Ok<TenderRejectResponse>():
|
feedbacks[index] = _feedbackData!;
|
||||||
// break;
|
} else {
|
||||||
// case Error<TenderRejectResponse>():
|
feedbacks.add(_feedbackData!);
|
||||||
// break;
|
}
|
||||||
// }
|
}
|
||||||
}
|
break;
|
||||||
|
case Error<FeedbackResponse>():
|
||||||
/// Sets a tender as submitted
|
_errorMessage = result.error.toString();
|
||||||
Future<void> markSubmitted(TenderModel tender) async {
|
break;
|
||||||
// _updateTenderState(
|
}
|
||||||
// tender.tenderId!,
|
notifyListeners();
|
||||||
// submitted: true,
|
_errorMessage = null;
|
||||||
// liked: tender.liked,
|
notifyListeners();
|
||||||
// disliked: false,
|
|
||||||
// rejected: false,
|
|
||||||
// );
|
|
||||||
// notifyListeners();
|
|
||||||
// final result = await _tendersRepository.submitTender();
|
|
||||||
// switch (result) {
|
|
||||||
// case Ok<TenderSubmitResponse>():
|
|
||||||
// break;
|
|
||||||
// case Error<TenderSubmitResponse>():
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clears a specific state for a tender
|
|
||||||
void clearTenderState(
|
|
||||||
TenderModel tenderModel, {
|
|
||||||
bool? isLiked,
|
|
||||||
bool? isDisliked,
|
|
||||||
bool? isRejected,
|
|
||||||
bool? isSubmitted,
|
|
||||||
}) {
|
|
||||||
// _updateTenderState(
|
|
||||||
// tenderModel.tenderId!,
|
|
||||||
// liked: isLiked ?? tenderModel.liked,
|
|
||||||
// disliked: isDisliked ?? tenderModel.disliked,
|
|
||||||
// rejected: isRejected ?? tenderModel.rejected,
|
|
||||||
// submitted: isSubmitted ?? tenderModel.submitted,
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Toggles like state for a tender
|
|
||||||
void toggleLike(TenderModel tender) {
|
|
||||||
// if (tender.liked == true) {
|
|
||||||
// clearTenderState(tender, isLiked: false);
|
|
||||||
// } else {
|
|
||||||
// markLiked(tender);
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Toggles dislike state for a tender
|
|
||||||
void toggleDislike(TenderModel tender) {
|
|
||||||
// if (tender.disliked == true) {
|
|
||||||
// clearTenderState(tender, isDisliked: false);
|
|
||||||
// } else {
|
|
||||||
// markDisliked(tender);
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Toggles reject state for a tender
|
|
||||||
void toggleReject(TenderModel tender) {
|
|
||||||
// if (tender.rejected == true) {
|
|
||||||
// clearTenderState(tender, isRejected: false);
|
|
||||||
// } else {
|
|
||||||
// markRejected(tender);
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Toggles submit state for a tender
|
|
||||||
void toggleSubmit(TenderModel tender) {
|
|
||||||
// if (tender.submitted == true) {
|
|
||||||
// clearTenderState(tender, isSubmitted: false);
|
|
||||||
// } else {
|
|
||||||
// markSubmitted(tender);
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tm_app/core/theme/colors.dart';
|
import 'package:tm_app/core/theme/colors.dart';
|
||||||
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
||||||
|
import 'package:tm_app/view_models/tenders_view_model.dart';
|
||||||
|
|
||||||
import '../../../core/constants/assets.dart';
|
import '../../../core/constants/assets.dart';
|
||||||
import '../../../core/utils/size_config.dart';
|
import '../../../core/utils/size_config.dart';
|
||||||
@@ -26,29 +28,45 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
|
|||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
|
|
||||||
void _goToPreviousPage() {
|
void _goToPreviousPage() {
|
||||||
|
if (currentPage == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pageController.previousPage(
|
pageController.previousPage(
|
||||||
duration: Duration(milliseconds: 300),
|
duration: Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOutCubic,
|
curve: Curves.easeInOutCubic,
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
if (currentPage == 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentPage = currentPage - 1;
|
currentPage = currentPage - 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch feedback 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _goToNextPage() {
|
void _goToNextPage() {
|
||||||
|
if (currentPage == widget.tenders.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pageController.nextPage(
|
pageController.nextPage(
|
||||||
duration: Duration(milliseconds: 300),
|
duration: Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOutCubic,
|
curve: Curves.easeInOutCubic,
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
if (currentPage == widget.tenders.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentPage = currentPage + 1;
|
currentPage = currentPage + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch feedback 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -76,6 +94,19 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
currentPage = index + 1;
|
currentPage = index + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch feedback 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!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we need to load more tenders (when user reaches near the end)
|
||||||
|
if (index >= widget.tenders.length - 1 &&
|
||||||
|
viewModel.hasMoreData &&
|
||||||
|
!viewModel.isLoadingMore) {
|
||||||
|
viewModel.loadMoreTenders();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final tender = widget.tenders[index];
|
final tender = widget.tenders[index];
|
||||||
@@ -119,13 +150,31 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _pageNumberText() {
|
Widget _pageNumberText() {
|
||||||
return Text(
|
final viewModel = context.watch<TendersViewModel>();
|
||||||
'$currentPage/${widget.tenders.length}',
|
return Column(
|
||||||
style: TextStyle(
|
mainAxisSize: MainAxisSize.min,
|
||||||
fontSize: 14.0.sp(),
|
children: [
|
||||||
fontWeight: FontWeight.w500,
|
Text(
|
||||||
color: AppColors.grey,
|
'$currentPage/${widget.tenders.length}',
|
||||||
),
|
style: TextStyle(
|
||||||
|
fontSize: 14.0.sp(),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,24 +21,27 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final viewModel = context.watch<TendersViewModel>();
|
return Consumer<TendersViewModel>(
|
||||||
return Row(
|
builder: (context, viewModel, child) {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
return Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
SizedBox(width: 16.0.w()),
|
children: [
|
||||||
|
SizedBox(width: 16.0.w()),
|
||||||
|
|
||||||
// Dislike button
|
// Dislike button
|
||||||
_dislikeButton(viewModel),
|
_dislikeButton(viewModel),
|
||||||
SizedBox(width: 32.0.w()),
|
SizedBox(width: 32.0.w()),
|
||||||
//reject button
|
//reject button
|
||||||
_rejectButton(viewModel),
|
_rejectButton(viewModel),
|
||||||
SizedBox(width: 32.0.w()),
|
SizedBox(width: 32.0.w()),
|
||||||
//submit button
|
//submit button
|
||||||
_submitButton(viewModel),
|
_submitButton(viewModel),
|
||||||
SizedBox(width: 32.0.w()),
|
SizedBox(width: 32.0.w()),
|
||||||
// Like button
|
// Like button
|
||||||
_likeButton(viewModel),
|
_likeButton(viewModel),
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +157,16 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _dislikeButton(TendersViewModel viewModel) {
|
Widget _dislikeButton(TendersViewModel viewModel) {
|
||||||
|
// Find feedback for this specific tender
|
||||||
|
final feedback = viewModel.getFeedbackForTender(tender.id!);
|
||||||
|
final isDisliked = feedback?.feedbackType == 'dislike';
|
||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: AppStrings.dislike,
|
message: AppStrings.dislike,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// viewModel.toggleDislike(tender);
|
viewModel.feedback(tenderId: tender.id!, feedbackType: 'dislike');
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -169,10 +176,7 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
AssetsManager.dislike,
|
AssetsManager.dislike,
|
||||||
colorFilter: ColorFilter.mode(
|
colorFilter: ColorFilter.mode(
|
||||||
// tender.disliked ?? false
|
isDisliked ? AppColors.errorColor : AppColors.grey50,
|
||||||
// ? AppColors.errorColor
|
|
||||||
// :
|
|
||||||
AppColors.grey50,
|
|
||||||
BlendMode.srcATop,
|
BlendMode.srcATop,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -183,11 +187,7 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12.0.sp(),
|
fontSize: 12.0.sp(),
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color:
|
color: isDisliked ? AppColors.errorColor : AppColors.grey50,
|
||||||
// tender.disliked ?? false
|
|
||||||
// ? AppColors.errorColor
|
|
||||||
// :
|
|
||||||
AppColors.grey50,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -197,12 +197,16 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _likeButton(TendersViewModel viewModel) {
|
Widget _likeButton(TendersViewModel viewModel) {
|
||||||
|
// Find feedback for this specific tender
|
||||||
|
final feedback = viewModel.getFeedbackForTender(tender.id!);
|
||||||
|
final isLiked = feedback?.feedbackType == 'like';
|
||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: AppStrings.like,
|
message: AppStrings.like,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// viewModel.toggleLike(tender);
|
viewModel.feedback(tenderId: tender.id!, feedbackType: 'like');
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -212,10 +216,7 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
AssetsManager.like,
|
AssetsManager.like,
|
||||||
colorFilter: ColorFilter.mode(
|
colorFilter: ColorFilter.mode(
|
||||||
// tender.liked ?? false
|
isLiked ? AppColors.successColor : AppColors.grey50,
|
||||||
// ? AppColors.successColor
|
|
||||||
// :
|
|
||||||
AppColors.grey50,
|
|
||||||
BlendMode.srcATop,
|
BlendMode.srcATop,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -226,11 +227,7 @@ class TenderActionButtonsRow extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12.0.sp(),
|
fontSize: 12.0.sp(),
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color:
|
color: isLiked ? AppColors.successColor : AppColors.grey50,
|
||||||
// tender.liked ?? false
|
|
||||||
// ? AppColors.successColor
|
|
||||||
// :
|
|
||||||
AppColors.grey50,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user