added feedback

This commit is contained in:
amirrezaghabeli
2025-08-18 15:33:50 +03:30
parent d9d5502e79
commit 3dca9fd383
8 changed files with 231 additions and 229 deletions
@@ -1,4 +1,5 @@
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/tenders/tender_dislike_response/tender_dislike_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';
@@ -15,6 +16,22 @@ class TendersRepository {
return _tendersService.getTenders();
}
Future<Result<FeedbackResponse>> getTenderFeedback({
required String tenderId,
}) async {
return _tendersService.getTenderFeedback(tenderId: tenderId);
}
Future<Result<FeedbackResponse>> feedback({
required String tenderId,
required String feedbackType,
}) async {
return _tendersService.feedback(
tenderId: tenderId,
feedbackType: feedbackType,
);
}
Future<Result<TenderLikeResponse>> likeTender() async {
return _tendersService.likeTender();
}
@@ -13,7 +13,7 @@ part 'feedback_response.g.dart';
abstract class FeedbackResponse with _$FeedbackResponse {
const factory FeedbackResponse({
@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,
required String? message,
required bool? success,
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
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
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,12 +28,12 @@ $FeedbackResponseCopyWith<FeedbackResponse> get copyWith => _$FeedbackResponseCo
@override
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)
@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
String toString() {
@@ -48,11 +48,11 @@ abstract mixin class $FeedbackResponseCopyWith<$Res> {
factory $FeedbackResponseCopyWith(FeedbackResponse value, $Res Function(FeedbackResponse) _then) = _$FeedbackResponseCopyWithImpl;
@useResult
$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
@@ -69,7 +69,7 @@ class _$FeedbackResponseCopyWithImpl<$Res>
return _then(_self.copyWith(
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 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 String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,
@@ -91,6 +91,18 @@ $MetaCopyWith<$Res>? get meta {
/// with the given fields replaced by the non-null parameter values.
@override
@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 {
if (_self.error == 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) {
case _FeedbackResponse() when $default != null:
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) {
case _FeedbackResponse():
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) {
case _FeedbackResponse() when $default != null:
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()
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);
@override@JsonKey(name: 'meta') final Meta? meta;
final List<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: 'data') final FeedbackData? data;
@override@JsonKey(name: 'error') final ErrorModel? error;
@override final String? message;
@override final bool? success;
@@ -267,12 +271,12 @@ Map<String, dynamic> toJson() {
@override
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)
@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
String toString() {
@@ -287,11 +291,11 @@ abstract mixin class _$FeedbackResponseCopyWith<$Res> implements $FeedbackRespon
factory _$FeedbackResponseCopyWith(_FeedbackResponse value, $Res Function(_FeedbackResponse) _then) = __$FeedbackResponseCopyWithImpl;
@override @useResult
$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
@@ -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,}) {
return _then(_FeedbackResponse(
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 List<FeedbackData>?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as Meta?,data: freezed == data ? _self.data : data // 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 String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool?,
@@ -331,6 +335,18 @@ $MetaCopyWith<$Res>? get meta {
/// with the given fields replaced by the non-null parameter values.
@override
@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 {
if (_self.error == null) {
return null;
@@ -13,9 +13,9 @@ _FeedbackResponse _$FeedbackResponseFromJson(Map<String, dynamic> json) =>
? null
: Meta.fromJson(json['meta'] as Map<String, dynamic>),
data:
(json['data'] as List<dynamic>?)
?.map((e) => FeedbackData.fromJson(e as Map<String, dynamic>))
.toList(),
json['data'] == null
? null
: FeedbackData.fromJson(json['data'] as Map<String, dynamic>),
error:
json['error'] == null
? null
+31
View File
@@ -1,6 +1,9 @@
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:tm_app/core/utils/logger.dart';
import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
import 'package:tm_app/data/services/model/tenders/tender_dislike_response/tender_dislike_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';
@@ -23,6 +26,34 @@ class TendersService {
return result;
}
Future<Result<FeedbackResponse>> getTenderFeedback({
required String tenderId,
}) async {
final result = await _networkManager.makeRequest(
'/api/v1/feedback/tender/$tenderId',
method: 'GET',
(json) => FeedbackResponse.fromJson(json),
);
return result;
}
Future<Result<FeedbackResponse>> feedback({
required String tenderId,
required String feedbackType,
}) async {
final data = jsonEncode({
'feedback_type': feedbackType,
'tender_id': tenderId,
});
final result = await _networkManager.makeRequest(
'/api/v1/feedback',
method: 'POST',
(json) => FeedbackResponse.fromJson(json),
data: data,
);
return result;
}
Future<Result<TenderLikeResponse>> likeTender() async {
try {
// final result = await _networkManager.makeRequest(
+72 -154
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.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 '../core/utils/result.dart';
@@ -18,13 +19,31 @@ class TendersViewModel with ChangeNotifier {
bool _isLoading = false;
String? _errorMessage;
TendersResponse? _tendersResponse;
FeedbackData? _feedbackData;
bool get isLoading => _isLoading;
String? get errorMessage => _errorMessage;
TendersResponse? get tendersResponse => _tendersResponse;
FeedbackData? get feedbackData => _feedbackData;
List<FeedbackData> feedbacks = [];
int currentPage = 1;
/// Get feedback for a specific tender
FeedbackData? getFeedbackForTender(String tenderId) {
try {
return feedbacks.firstWhere((f) => f.tender == tenderId);
} on Exception {
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 {
_isLoading = true;
_errorMessage = null;
@@ -34,6 +53,7 @@ class TendersViewModel with ChangeNotifier {
switch (result) {
case Ok<TendersResponse>():
_tendersResponse = result.value;
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
break;
case Error<TendersResponse>():
_errorMessage = result.error.toString();
@@ -45,166 +65,64 @@ class TendersViewModel with ChangeNotifier {
notifyListeners();
}
/// Updates a tender's state in the list
void _updateTenderState(
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();
Future<void> getTenderFeedback(String tenderId) async {
// _isLoading = true;
_errorMessage = null;
notifyListeners();
// _tendersResponse = _tendersResponse!.copyWith(
// tendersData: _tendersResponse!.tendersData!.copyWith(
// tenders: updatedTenders,
// ),
// );
// }
final result = await _tendersRepository.getTenderFeedback(
tenderId: tenderId,
);
switch (result) {
case Ok<FeedbackResponse>():
_feedbackData = result.value.data;
// Add or update _feedbackData in feedbacks list by tender id
_addOrUpdateFunction(_feedbackData!);
break;
case Error<FeedbackResponse>():
_errorMessage = result.error.toString();
break;
}
// _isLoading = false;
notifyListeners();
_errorMessage = null;
notifyListeners();
}
/// Sets a tender as liked
Future<void> markLiked(TenderModel tender) async {
// _updateTenderState(
// tender.id!,
// liked: true,
// disliked: false,
// rejected: false,
// submitted: tender.submitted,
// );
// notifyListeners();
// final result = await _tendersRepository.likeTender();
// switch (result) {
// case Ok<TenderLikeResponse>():
// break;
// case Error<TenderLikeResponse>():
// break;
// }
Future<void> feedback({
required String tenderId,
required String feedbackType,
}) async {
_errorMessage = null;
notifyListeners();
final result = await _tendersRepository.feedback(
tenderId: tenderId,
feedbackType: feedbackType,
);
switch (result) {
case Ok<FeedbackResponse>():
_feedbackData = result.value.data;
if (_feedbackData != null) {
_addOrUpdateFunction(_feedbackData!);
}
/// Sets a tender as disliked
Future<void> markDisliked(TenderModel tender) async {
// _updateTenderState(
// tender.tenderId!,
// disliked: true,
// liked: false,
// rejected: tender.rejected,
// submitted: false,
// );
// notifyListeners();
// final result = await _tendersRepository.dislikeTender();
// switch (result) {
// case Ok<TenderDislikeResponse>():
// break;
// case Error<TenderDislikeResponse>():
// break;
// }
break;
case Error<FeedbackResponse>():
_errorMessage = result.error.toString();
break;
}
notifyListeners();
_errorMessage = null;
notifyListeners();
}
/// Sets a tender as rejected
Future<void> markRejected(TenderModel tender) async {
// _updateTenderState(
// tender.tenderId!,
// rejected: true,
// liked: false,
// disliked: tender.disliked,
// submitted: false,
// );
// notifyListeners();
// final result = await _tendersRepository.rejectTender();
// switch (result) {
// case Ok<TenderRejectResponse>():
// break;
// case Error<TenderRejectResponse>():
// break;
// }
void _addOrUpdateFunction(FeedbackData feedbackData) {
final index = feedbacks.indexWhere((f) => f.tender == feedbackData.tender);
if (index != -1) {
feedbacks[index] = feedbackData;
} else {
feedbacks.add(feedbackData);
}
/// Sets a tender as submitted
Future<void> markSubmitted(TenderModel tender) async {
// _updateTenderState(
// tender.tenderId!,
// submitted: true,
// liked: tender.liked,
// 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_svg/svg.dart';
import 'package:provider/provider.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/view_models/tenders_view_model.dart';
import '../../../core/constants/assets.dart';
import '../../../core/utils/size_config.dart';
@@ -26,29 +28,45 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
int currentPage = 1;
void _goToPreviousPage() {
if (currentPage == 1) {
return;
}
pageController.previousPage(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutCubic,
);
setState(() {
if (currentPage == 1) {
return;
}
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() {
if (currentPage == widget.tenders.length) {
return;
}
pageController.nextPage(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutCubic,
);
setState(() {
if (currentPage == widget.tenders.length) {
return;
}
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
@@ -76,6 +94,11 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
setState(() {
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!);
}
},
itemBuilder: (context, index) {
final tender = widget.tenders[index];
@@ -21,7 +21,8 @@ class TenderActionButtonsRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final viewModel = context.watch<TendersViewModel>();
return Consumer<TendersViewModel>(
builder: (context, viewModel, child) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -40,6 +41,8 @@ class TenderActionButtonsRow extends StatelessWidget {
_likeButton(viewModel),
],
);
},
);
}
Widget _rejectButton(TendersViewModel viewModel) {
@@ -154,12 +157,16 @@ class TenderActionButtonsRow extends StatelessWidget {
}
Widget _dislikeButton(TendersViewModel viewModel) {
// Find feedback for this specific tender
final feedback = viewModel.getFeedbackForTender(tender.id!);
final isDisliked = feedback?.feedbackType == 'dislike';
return Tooltip(
message: AppStrings.dislike,
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
// viewModel.toggleDislike(tender);
viewModel.feedback(tenderId: tender.id!, feedbackType: 'dislike');
},
child: Column(
children: [
@@ -169,10 +176,7 @@ class TenderActionButtonsRow extends StatelessWidget {
fit: BoxFit.cover,
AssetsManager.dislike,
colorFilter: ColorFilter.mode(
// tender.disliked ?? false
// ? AppColors.errorColor
// :
AppColors.grey50,
isDisliked ? AppColors.errorColor : AppColors.grey50,
BlendMode.srcATop,
),
),
@@ -183,11 +187,7 @@ class TenderActionButtonsRow extends StatelessWidget {
style: TextStyle(
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
color:
// tender.disliked ?? false
// ? AppColors.errorColor
// :
AppColors.grey50,
color: isDisliked ? AppColors.errorColor : AppColors.grey50,
),
),
],
@@ -197,12 +197,16 @@ class TenderActionButtonsRow extends StatelessWidget {
}
Widget _likeButton(TendersViewModel viewModel) {
// Find feedback for this specific tender
final feedback = viewModel.getFeedbackForTender(tender.id!);
final isLiked = feedback?.feedbackType == 'like';
return Tooltip(
message: AppStrings.like,
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
// viewModel.toggleLike(tender);
viewModel.feedback(tenderId: tender.id!, feedbackType: 'like');
},
child: Column(
children: [
@@ -212,10 +216,7 @@ class TenderActionButtonsRow extends StatelessWidget {
fit: BoxFit.cover,
AssetsManager.like,
colorFilter: ColorFilter.mode(
// tender.liked ?? false
// ? AppColors.successColor
// :
AppColors.grey50,
isLiked ? AppColors.successColor : AppColors.grey50,
BlendMode.srcATop,
),
),
@@ -226,11 +227,7 @@ class TenderActionButtonsRow extends StatelessWidget {
style: TextStyle(
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
color:
// tender.liked ?? false
// ? AppColors.successColor
// :
AppColors.grey50,
color: isLiked ? AppColors.successColor : AppColors.grey50,
),
),
],