filters in your tenders fixed
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:tm_app/core/utils/result.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
|
||||
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
|
||||
import 'package:tm_app/data/services/your_tenders_service.dart';
|
||||
|
||||
@@ -7,8 +8,18 @@ class YourTendersRepository {
|
||||
YourTendersRepository({required YourTendersService yourTendersService})
|
||||
: _yourTendersService = yourTendersService;
|
||||
|
||||
Future<Result<TenderApprovalsResponse>> getApprovedTenders() {
|
||||
return _yourTendersService.getApprovedTenders();
|
||||
Future<Result<TenderApprovalsResponse>> getApprovedTenders({
|
||||
required int limit,
|
||||
required int offset,
|
||||
required String createdFrom,
|
||||
required String createdTo,
|
||||
}) {
|
||||
return _yourTendersService.getApprovedTenders(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
createdFrom: createdFrom,
|
||||
createdTo: createdTo,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Result<TenderApprovalsResponse>> getTenders({
|
||||
@@ -24,4 +35,20 @@ class YourTendersRepository {
|
||||
createdTo: createdTo,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Result<LikedTendersResponse>> getTendersFeedback({
|
||||
required int limit,
|
||||
required int offset,
|
||||
required String feedbackType,
|
||||
required String dateFrom,
|
||||
required String dateTo,
|
||||
}) {
|
||||
return _yourTendersService.getTendersFeedback(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
feedbackType: feedbackType,
|
||||
dateFrom: dateFrom,
|
||||
dateTo: dateTo,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,19 @@ class YourTendersApi {
|
||||
static const String tenderApprovalsStatus =
|
||||
'/api/v1/tender-approvals?status=submitted';
|
||||
|
||||
static String getTenderApprovalsStatus({
|
||||
required int limit,
|
||||
required int offset,
|
||||
required String createdFrom,
|
||||
required String createdTo,
|
||||
}) {
|
||||
if (createdFrom.isNotEmpty && createdTo.isNotEmpty) {
|
||||
return '$tenderApprovalsStatus&created_from=$createdFrom&created_to=$createdTo';
|
||||
}
|
||||
return tenderApprovalsStatus;
|
||||
}
|
||||
// return '$tenderApprovalsStatus?limit=$limit&offset=$offset';
|
||||
|
||||
static const String tenderApproval = '/api/v1/tender-approvals';
|
||||
|
||||
static String getTenders({
|
||||
@@ -15,4 +28,19 @@ class YourTendersApi {
|
||||
}
|
||||
return '$tenderApproval?limit=$limit&offset=$offset';
|
||||
}
|
||||
|
||||
static const String tendersFeedback = '/api/v1/feedback';
|
||||
|
||||
static String getTendersFeedback({
|
||||
required int limit,
|
||||
required int offset,
|
||||
required String feedbackType,
|
||||
required String dateFrom,
|
||||
required String dateTo,
|
||||
}) {
|
||||
if (dateFrom.isNotEmpty && dateTo.isNotEmpty) {
|
||||
return '$tendersFeedback?feedback_type=$feedbackType&limit=$limit&offset=$offset&date_from=$dateFrom&date_to=$dateTo';
|
||||
}
|
||||
return '$tendersFeedback?feedback_type=$feedbackType&limit=$limit&offset=$offset';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
const String homeMockData = '''
|
||||
{
|
||||
"data": {
|
||||
"partnership": "0.75",
|
||||
"self_apply": "12",
|
||||
"contracting": "36",
|
||||
"tender_submitted": "12",
|
||||
"approved_tenders": "03",
|
||||
"tender_value": "\$250,000",
|
||||
"thunder_status": "23",
|
||||
"your_tenders": [
|
||||
{
|
||||
"created_time": "2025-01-01",
|
||||
"tender_id": "1234567890",
|
||||
"status": "Completed",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.Lorem ipsum dolor sit amet consectetur",
|
||||
"location": "Sweden",
|
||||
"type": "Self Apply"
|
||||
},
|
||||
{
|
||||
"created_time": "2025-01-01",
|
||||
"tender_id": "1234567890",
|
||||
"status": "Completed",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.Lorem ipsum dolor sit amet consectetur",
|
||||
"location": "Sweden",
|
||||
"type": "Partner Ship"
|
||||
},
|
||||
{
|
||||
"created_time": "2025-01-01",
|
||||
"tender_id": "1234567890",
|
||||
"status": "Completed",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.Lorem ipsum dolor sit amet consectetur",
|
||||
"location": "Sweden",
|
||||
"type": "Self Apply"
|
||||
},
|
||||
{
|
||||
"created_time": "2025-01-01",
|
||||
"tender_id": "1234567890",
|
||||
"status": "Completed",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.Lorem ipsum dolor sit amet consectetur",
|
||||
"location": "Sweden",
|
||||
"type": "Partner Ship"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
''';
|
||||
@@ -1,62 +0,0 @@
|
||||
const String mockYourTendersData = '''
|
||||
{
|
||||
"approvedTenders": [
|
||||
{
|
||||
"date": "2025-05-21",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Volutpat velit tincidunt amet diam. Placerat congue ut Sed facilisis faucibus porttitor. Proin suspendisse eu euismod sit lorem quis. Suscipit ...",
|
||||
"location": "Sweden",
|
||||
"countryFlag": "assets/icons/SE.png",
|
||||
"status": "Completed",
|
||||
"projectStatus": "Self Apply"
|
||||
},
|
||||
{
|
||||
"date": "2025-05-21",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Volutpat velit tincidunt amet diam. Placerat congue ut Sed facilisis faucibus porttitor.",
|
||||
"location": "Thailand",
|
||||
"countryFlag": "assets/icons/SE.png",
|
||||
"status": "Completed",
|
||||
"projectStatus": "Partner Ship"
|
||||
},
|
||||
{
|
||||
"date": "2025-05-21",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Volutpat facilisis faucibus porttitor. Proin suspendisse eu euismod sit lorem quis.",
|
||||
"location": "Italy",
|
||||
"countryFlag": "assets/icons/SE.png",
|
||||
"status": "Completed",
|
||||
"projectStatus": "Self Apply"
|
||||
}
|
||||
],
|
||||
"tendersSubmitted": [
|
||||
{
|
||||
"date": "2025-05-21",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Volutpat velit tincidunt amet diam. Placerat congue ut Sed facilisis faucibus porttitor. Proin suspendisse eu euismod sit lorem quis.",
|
||||
"location": "Sweden",
|
||||
"countryFlag": "assets/icons/SE.png",
|
||||
"status": "Won",
|
||||
"projectStatus": "Self Apply"
|
||||
},
|
||||
{
|
||||
"date": "2025-05-21",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur. Sed mi tortor eu purus senectus.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Volutpat velit tincidunt amet diam. Placerat congue ut Sed facilisis faucibus porttitor.",
|
||||
"location": "Thailand",
|
||||
"countryFlag": "assets/icons/SE.png",
|
||||
"status": "Reject",
|
||||
"projectStatus": "Partner Ship"
|
||||
},
|
||||
{
|
||||
"date": "2025-05-21",
|
||||
"title": "Lorem ipsum dolor sit amet consectetur.",
|
||||
"description": "Lorem ipsum dolor sit amet consectetur. Volutpat facilisis faucibus porttitor. Proin suspendisse eu euismod sit lorem quis.",
|
||||
"location": "Italy",
|
||||
"countryFlag": "assets/icons/SE.png",
|
||||
"status": "Won",
|
||||
"projectStatus": "Self Apply"
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
@@ -1,24 +0,0 @@
|
||||
const tenderDetailMockData = '''
|
||||
{
|
||||
"data": {
|
||||
"date": "2025-05-21",
|
||||
"status": "Open",
|
||||
"title": "Operation, support and further development of open e-platform Operation, support and further development of open e-platform",
|
||||
"id": "JNDFKMDV-100JF",
|
||||
"approvalDate": "2025-05-21",
|
||||
"submissionDate": "2025-05-21",
|
||||
"client": "Procurement Notice Procurement NoticeProcurement Notice",
|
||||
"deliveryLocation": "Norrbotten County",
|
||||
"referenceNumber": "KLF 2025/120",
|
||||
"country": "UK",
|
||||
"flagAsset": "assets/icons/SE.png",
|
||||
"locationTitle": "Lorem ipsum is amet",
|
||||
"locationDescription": "Luleå Municipality is procuring on behalf of Norrbotten’s e-board (all municipalities in Norrbotten). The procurement includes operation, support, and further development of the existing open e-platform. No additional information, amendments, or answers to questions will be provided after June 16.",
|
||||
"documentName": "PDF, Document",
|
||||
"documentUrl": "https://www.tenders.com",
|
||||
"profileMatch": 0.75,
|
||||
"incompleteResume": true,
|
||||
"incompleteResumeReason": "No experience in e-platform development"
|
||||
}
|
||||
}
|
||||
''';
|
||||
@@ -1,76 +0,0 @@
|
||||
final String tendersMockData = '''
|
||||
{
|
||||
"tenders": [
|
||||
{
|
||||
"tender_id": "KLF 2025/120",
|
||||
"title": "Tender 1",
|
||||
"description": "Description 1",
|
||||
"created_time": "2021-01-01",
|
||||
"deadline": "2025-06-15",
|
||||
"location": "Sweden",
|
||||
"type": "Self Apply",
|
||||
"profile_match": 75,
|
||||
"liked": false,
|
||||
"disliked": false,
|
||||
"rejected": false,
|
||||
"submitted": false
|
||||
},
|
||||
{
|
||||
"tender_id": "KLF 2025/121",
|
||||
"title": "Tender 2",
|
||||
"description": "Description 2",
|
||||
"created_time": "2021-02-01",
|
||||
"deadline": "2025-07-20",
|
||||
"location": "Norway",
|
||||
"type": "Invitation",
|
||||
"profile_match": 85,
|
||||
"liked": false,
|
||||
"disliked": false,
|
||||
"rejected": false,
|
||||
"submitted": false
|
||||
},
|
||||
{
|
||||
"tender_id": "KLF 2025/122",
|
||||
"title": "Tender 3",
|
||||
"description": "Description 3",
|
||||
"created_time": "2021-03-01",
|
||||
"deadline": "2025-08-10",
|
||||
"location": "Finland",
|
||||
"type": "Self Apply",
|
||||
"profile_match": 65,
|
||||
"liked": false,
|
||||
"disliked": false,
|
||||
"rejected": false,
|
||||
"submitted": false
|
||||
},
|
||||
{
|
||||
"tender_id": "KLF 2025/123",
|
||||
"title": "Tender 4",
|
||||
"description": "Description 4",
|
||||
"created_time": "2021-04-01",
|
||||
"deadline": "2025-09-05",
|
||||
"location": "Denmark",
|
||||
"type": "Invitation",
|
||||
"profile_match": 90,
|
||||
"liked": false,
|
||||
"disliked": false,
|
||||
"rejected": false,
|
||||
"submitted": false
|
||||
},
|
||||
{
|
||||
"tender_id": "KLF 2025/124",
|
||||
"title": "Tender 5",
|
||||
"description": "Description 5",
|
||||
"created_time": "2021-05-01",
|
||||
"deadline": "2025-10-12",
|
||||
"location": "Iceland",
|
||||
"type": "Self Apply",
|
||||
"profile_match": 70,
|
||||
"liked": false,
|
||||
"disliked": false,
|
||||
"rejected": false,
|
||||
"submitted": false
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:tm_app/core/utils/result.dart';
|
||||
import 'package:tm_app/data/services/api/your_tenders_api.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
|
||||
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
|
||||
|
||||
import '../../../core/network/network_manager.dart';
|
||||
@@ -10,9 +11,19 @@ class YourTendersService {
|
||||
|
||||
final NetworkManager _networkManager;
|
||||
|
||||
Future<Result<TenderApprovalsResponse>> getApprovedTenders() async {
|
||||
Future<Result<TenderApprovalsResponse>> getApprovedTenders({
|
||||
required int limit,
|
||||
required int offset,
|
||||
required String createdFrom,
|
||||
required String createdTo,
|
||||
}) async {
|
||||
final result = await _networkManager.makeRequest(
|
||||
YourTendersApi.tenderApprovalsStatus,
|
||||
YourTendersApi.getTenderApprovalsStatus(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
createdFrom: createdFrom,
|
||||
createdTo: createdTo,
|
||||
),
|
||||
(json) => TenderApprovalsResponse.fromJson(json),
|
||||
method: 'GET',
|
||||
);
|
||||
@@ -38,4 +49,25 @@ class YourTendersService {
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Result<LikedTendersResponse>> getTendersFeedback({
|
||||
required int limit,
|
||||
required int offset,
|
||||
required String feedbackType,
|
||||
required String dateFrom,
|
||||
required String dateTo,
|
||||
}) async {
|
||||
final result = await _networkManager.makeRequest(
|
||||
YourTendersApi.getTendersFeedback(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
feedbackType: feedbackType,
|
||||
dateFrom: dateFrom,
|
||||
dateTo: dateTo,
|
||||
),
|
||||
(json) => LikedTendersResponse.fromJson(json),
|
||||
method: 'GET',
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tm_app/core/utils/result.dart';
|
||||
import 'package:tm_app/data/repositories/your_tenders_repository.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
|
||||
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
|
||||
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
||||
|
||||
class YourTendersViewModel with ChangeNotifier {
|
||||
final YourTendersRepository yourTendersRepository;
|
||||
@@ -11,7 +13,13 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
bool isLoading = false;
|
||||
String? errorMessage;
|
||||
TenderApprovalsResponse? data;
|
||||
|
||||
LikedTendersResponse? likedTendersData;
|
||||
// Pagination state for feedback lists
|
||||
bool isLoadingMore = false;
|
||||
bool hasMore = true;
|
||||
int _offset = 0;
|
||||
final int _limit = 10;
|
||||
String? _currentFeedbackType;
|
||||
// Filter States
|
||||
DateTimeRange? selectedDateRange;
|
||||
String selectedStatus = 'All';
|
||||
@@ -27,21 +35,29 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
? _fmt.format(selectedDateRange!.end)
|
||||
: 'YYYY/MM/DD';
|
||||
|
||||
int get startDateUnix =>
|
||||
String get startDateUnix =>
|
||||
selectedDateRange?.start != null
|
||||
? selectedDateRange!.start.millisecondsSinceEpoch ~/ 1000
|
||||
: 0;
|
||||
? (selectedDateRange!.start.millisecondsSinceEpoch ~/ 1000).toString()
|
||||
: '';
|
||||
|
||||
int get endDateUnix =>
|
||||
String get endDateUnix =>
|
||||
selectedDateRange?.end != null
|
||||
? selectedDateRange!.end.millisecondsSinceEpoch ~/ 1000
|
||||
: 0;
|
||||
? (selectedDateRange!.end.millisecondsSinceEpoch ~/ 1000).toString()
|
||||
: '';
|
||||
|
||||
Future<void> getApprovedTenders() async {
|
||||
Future<void> getApprovedTenders({
|
||||
required int limit,
|
||||
required int offset,
|
||||
}) async {
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
final result = await yourTendersRepository.getApprovedTenders();
|
||||
final result = await yourTendersRepository.getApprovedTenders(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
createdFrom: startDateUnix,
|
||||
createdTo: endDateUnix,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<TenderApprovalsResponse>():
|
||||
@@ -86,6 +102,75 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> getTendersFeedback({
|
||||
required String feedbackType,
|
||||
bool reset = false,
|
||||
}) async {
|
||||
if (reset) {
|
||||
_offset = 0;
|
||||
hasMore = true;
|
||||
_currentFeedbackType = feedbackType;
|
||||
}
|
||||
|
||||
if (!reset && (isLoadingMore || !hasMore)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_offset == 0) {
|
||||
isLoading = true;
|
||||
} else {
|
||||
isLoadingMore = true;
|
||||
}
|
||||
notifyListeners();
|
||||
|
||||
final result = await yourTendersRepository.getTendersFeedback(
|
||||
limit: _limit,
|
||||
offset: _offset,
|
||||
feedbackType: _currentFeedbackType ?? feedbackType,
|
||||
dateFrom: startDateUnix,
|
||||
dateTo: endDateUnix,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<LikedTendersResponse>():
|
||||
final incoming = result.value;
|
||||
final incomingList = incoming.data?.feedback ?? [];
|
||||
|
||||
if (reset || likedTendersData == null) {
|
||||
likedTendersData = incoming;
|
||||
} else {
|
||||
final existingList = likedTendersData!.data?.feedback ?? [];
|
||||
final combined = List.of(existingList)..addAll(incomingList);
|
||||
final newMeta = incoming.data?.meta ?? likedTendersData!.data?.meta;
|
||||
likedTendersData = likedTendersData!.copyWith(
|
||||
data: likedTendersData!.data!.copyWith(
|
||||
feedback: combined,
|
||||
meta: newMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
hasMore = incomingList.length == _limit;
|
||||
_offset += _limit;
|
||||
errorMessage = null;
|
||||
break;
|
||||
case Error<LikedTendersResponse>():
|
||||
errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> loadMoreFeedback() async {
|
||||
if (_currentFeedbackType == null) {
|
||||
return;
|
||||
}
|
||||
await getTendersFeedback(feedbackType: _currentFeedbackType!, reset: false);
|
||||
}
|
||||
|
||||
// --- Filter Actions ---
|
||||
void setDateRange(DateTimeRange? range) {
|
||||
selectedDateRange = range;
|
||||
@@ -99,20 +184,24 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
|
||||
void clearFilter() {
|
||||
selectedDateRange = null;
|
||||
selectedStatus = 'All';
|
||||
selectedStatus = YourTendersStrings.all;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> callWithFilter() async {
|
||||
if (selectedStatus == 'All') {
|
||||
if (selectedStatus == YourTendersStrings.all) {
|
||||
await getTenders(
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
createdFrom: startDateUnix.toString(),
|
||||
createdTo: endDateUnix.toString(),
|
||||
createdFrom: startDateUnix,
|
||||
createdTo: endDateUnix,
|
||||
);
|
||||
} else if (selectedStatus == 'Tenders submitted') {
|
||||
await getApprovedTenders();
|
||||
} else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
|
||||
await getApprovedTenders(limit: 10, offset: 0);
|
||||
} else if (selectedStatus == YourTendersStrings.likeTenders) {
|
||||
await getTendersFeedback(feedbackType: 'like', reset: true);
|
||||
} else if (selectedStatus == YourTendersStrings.dislikeTenders) {
|
||||
await getTendersFeedback(feedbackType: 'dislike', reset: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/view_models/your_tenders_view_model.dart';
|
||||
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/filter_button.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/liked_disliked_tenders_list.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tablet_desktop_appbar.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart';
|
||||
|
||||
@@ -24,10 +26,6 @@ class _YourTendersDesktopPageState extends State<YourTendersDesktopPage>
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = TabController(length: 2, vsync: this);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<YourTendersViewModel>().getApprovedTenders();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -94,9 +92,28 @@ class _YourTendersDesktopPageState extends State<YourTendersDesktopPage>
|
||||
if (viewModel.errorMessage != null) {
|
||||
return Center(child: Text(viewModel.errorMessage!));
|
||||
}
|
||||
|
||||
if (viewModel.selectedStatus ==
|
||||
YourTendersStrings.likeTenders &&
|
||||
viewModel.likedTendersData != null) {
|
||||
return LikedDislikedTendersList(
|
||||
data: viewModel.likedTendersData!,
|
||||
status: 'liked',
|
||||
);
|
||||
} else if (viewModel.selectedStatus ==
|
||||
YourTendersStrings.dislikeTenders &&
|
||||
viewModel.likedTendersData != null) {
|
||||
return LikedDislikedTendersList(
|
||||
data: viewModel.likedTendersData!,
|
||||
status: 'disliked',
|
||||
);
|
||||
} else if (viewModel.data != null) {
|
||||
return TendersSubmitted(
|
||||
approvedTenders: viewModel.data!,
|
||||
);
|
||||
} else {
|
||||
return const Center(child: Text('No data available'));
|
||||
}
|
||||
// return TabBarView(
|
||||
// controller: controller,
|
||||
// children: [
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:tm_app/view_models/your_tenders_view_model.dart';
|
||||
import 'package:tm_app/views/shared/tender_app_bar.dart';
|
||||
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/filter_button.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/liked_disliked_tenders_list.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart';
|
||||
|
||||
class YourTendersMobilePage extends StatefulWidget {
|
||||
@@ -55,9 +56,33 @@ class _YourTendersMobilePageState extends State<YourTendersMobilePage> {
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
// Expanded(child: ApprovedTenders(tendersSubmitted: [])),
|
||||
if (viewModel.selectedStatus ==
|
||||
YourTendersStrings.likeTenders &&
|
||||
viewModel.likedTendersData != null)
|
||||
Expanded(
|
||||
child: TendersSubmitted(approvedTenders: viewModel.data!),
|
||||
child: LikedDislikedTendersList(
|
||||
data: viewModel.likedTendersData!,
|
||||
status: 'liked tenders',
|
||||
),
|
||||
)
|
||||
else if (viewModel.selectedStatus ==
|
||||
YourTendersStrings.dislikeTenders &&
|
||||
viewModel.likedTendersData != null)
|
||||
Expanded(
|
||||
child: LikedDislikedTendersList(
|
||||
data: viewModel.likedTendersData!,
|
||||
status: 'disliked',
|
||||
),
|
||||
)
|
||||
else if (viewModel.data != null)
|
||||
Expanded(
|
||||
child: TendersSubmitted(
|
||||
approvedTenders: viewModel.data!,
|
||||
),
|
||||
)
|
||||
else
|
||||
const Expanded(
|
||||
child: Center(child: Text('No data available')),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/your_tenders_view_model.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/filter_button.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/liked_disliked_tenders_list.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tablet_desktop_appbar.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart';
|
||||
|
||||
@@ -28,10 +29,6 @@ class _YourTendersTabletPageState extends State<YourTendersTabletPage>
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = TabController(length: 2, vsync: this);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<YourTendersViewModel>().getApprovedTenders();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -46,10 +43,7 @@ class _YourTendersTabletPageState extends State<YourTendersTabletPage>
|
||||
return Scaffold(
|
||||
key: key,
|
||||
backgroundColor: AppColors.backgroundColor,
|
||||
appBar: tabletAppBar(
|
||||
title: YourTendersStrings.yourTenders,
|
||||
key: key,
|
||||
),
|
||||
appBar: tabletAppBar(title: YourTendersStrings.yourTenders, key: key),
|
||||
drawer: TabletNavigationWidget(
|
||||
currentIndex: 1, // Home is index 0
|
||||
onTabChanged: (index) {
|
||||
@@ -102,7 +96,26 @@ class _YourTendersTabletPageState extends State<YourTendersTabletPage>
|
||||
if (viewModel.errorMessage != null) {
|
||||
return Center(child: Text(viewModel.errorMessage!));
|
||||
}
|
||||
|
||||
if (viewModel.selectedStatus ==
|
||||
YourTendersStrings.likeTenders &&
|
||||
viewModel.likedTendersData != null) {
|
||||
return LikedDislikedTendersList(
|
||||
data: viewModel.likedTendersData!,
|
||||
status: 'liked',
|
||||
);
|
||||
} else if (viewModel.selectedStatus ==
|
||||
YourTendersStrings.dislikeTenders &&
|
||||
viewModel.likedTendersData != null) {
|
||||
return LikedDislikedTendersList(
|
||||
data: viewModel.likedTendersData!,
|
||||
status: 'disliked',
|
||||
);
|
||||
} else if (viewModel.data != null) {
|
||||
return TendersSubmitted(approvedTenders: viewModel.data!);
|
||||
} else {
|
||||
return const Center(child: Text('No data available'));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
|
||||
import 'package:tm_app/view_models/your_tenders_view_model.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tender_card.dart';
|
||||
|
||||
class LikedDislikedTendersList extends StatefulWidget {
|
||||
final LikedTendersResponse data;
|
||||
final String status;
|
||||
|
||||
const LikedDislikedTendersList({
|
||||
required this.data,
|
||||
required this.status,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<LikedDislikedTendersList> createState() =>
|
||||
_LikedDislikedTendersListState();
|
||||
}
|
||||
|
||||
class _LikedDislikedTendersListState extends State<LikedDislikedTendersList> {
|
||||
final ScrollController _controller = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller.addListener(_onScroll);
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
final vm = context.read<YourTendersViewModel>();
|
||||
if (_controller.position.pixels >=
|
||||
_controller.position.maxScrollExtent - 200) {
|
||||
vm.loadMoreFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final vm = context.watch<YourTendersViewModel>();
|
||||
final data = widget.data;
|
||||
|
||||
if (data.data?.feedback == null || data.data!.feedback!.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
'No ${widget.status} found',
|
||||
style: TextStyle(fontSize: 16.0.sp(), color: AppColors.grey70),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final items = data.data!.feedback!;
|
||||
final itemCount = items.length + (vm.isLoadingMore ? 1 : 0);
|
||||
|
||||
return ListView.builder(
|
||||
controller: _controller,
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= items.length) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16.0.h()),
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(color: AppColors.secondary50),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final feedback = items[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 16.0.h()),
|
||||
child: TenderCard(
|
||||
date: feedback.tender!.publicationDate?.toString() ?? '',
|
||||
title: feedback.tender!.title ?? '',
|
||||
description: feedback.tender!.description ?? '',
|
||||
location: feedback.tender!.countryCode ?? '',
|
||||
countryCode: feedback.tender!.countryCode ?? '',
|
||||
status: feedback.tender!.status ?? '',
|
||||
projectStatus: feedback.tender!.procurementTypeCode!,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user