From 1e3bd9d9a8e2730ea75d78d204e6657a663efd9c Mon Sep 17 00:00:00 2001 From: amirrezaghabeli Date: Wed, 3 Sep 2025 13:25:40 +0330 Subject: [PATCH] filters in your tenders fixed --- .../repositories/your_tenders_repository.dart | 31 ++++- lib/data/services/api/your_tenders_api.dart | 28 +++++ .../services/mock_data/home_mock_data.dart | 51 -------- .../mock_data/mock_your_tenders_data.dart | 62 --------- .../mock_data/tender_detail_mock.dart | 24 ---- .../services/mock_data/tenders_mock_data.dart | 76 ----------- lib/data/services/your_tenders_service.dart | 36 +++++- lib/view_models/your_tenders_view_model.dart | 119 +++++++++++++++--- .../pages/your_tenders_desktop_page.dart | 31 +++-- .../pages/your_tenders_mobile_page.dart | 33 ++++- .../pages/your_tenders_tablet_page.dart | 31 +++-- .../widgets/liked_disliked_tenders_list.dart | 93 ++++++++++++++ 12 files changed, 363 insertions(+), 252 deletions(-) delete mode 100644 lib/data/services/mock_data/home_mock_data.dart delete mode 100644 lib/data/services/mock_data/mock_your_tenders_data.dart delete mode 100644 lib/data/services/mock_data/tender_detail_mock.dart delete mode 100644 lib/data/services/mock_data/tenders_mock_data.dart create mode 100644 lib/views/your_tenders/widgets/liked_disliked_tenders_list.dart diff --git a/lib/data/repositories/your_tenders_repository.dart b/lib/data/repositories/your_tenders_repository.dart index 7432d78..e059015 100644 --- a/lib/data/repositories/your_tenders_repository.dart +++ b/lib/data/repositories/your_tenders_repository.dart @@ -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> getApprovedTenders() { - return _yourTendersService.getApprovedTenders(); + Future> 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> getTenders({ @@ -24,4 +35,20 @@ class YourTendersRepository { createdTo: createdTo, ); } + + Future> 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, + ); + } } diff --git a/lib/data/services/api/your_tenders_api.dart b/lib/data/services/api/your_tenders_api.dart index ff30be2..8d520e2 100644 --- a/lib/data/services/api/your_tenders_api.dart +++ b/lib/data/services/api/your_tenders_api.dart @@ -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'; + } } diff --git a/lib/data/services/mock_data/home_mock_data.dart b/lib/data/services/mock_data/home_mock_data.dart deleted file mode 100644 index 40c6d17..0000000 --- a/lib/data/services/mock_data/home_mock_data.dart +++ /dev/null @@ -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" - } - ] - } -} -'''; diff --git a/lib/data/services/mock_data/mock_your_tenders_data.dart b/lib/data/services/mock_data/mock_your_tenders_data.dart deleted file mode 100644 index 64d6acd..0000000 --- a/lib/data/services/mock_data/mock_your_tenders_data.dart +++ /dev/null @@ -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" - } - ] -} -'''; diff --git a/lib/data/services/mock_data/tender_detail_mock.dart b/lib/data/services/mock_data/tender_detail_mock.dart deleted file mode 100644 index 4be8c1e..0000000 --- a/lib/data/services/mock_data/tender_detail_mock.dart +++ /dev/null @@ -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" - } -} -'''; \ No newline at end of file diff --git a/lib/data/services/mock_data/tenders_mock_data.dart b/lib/data/services/mock_data/tenders_mock_data.dart deleted file mode 100644 index 47f0a08..0000000 --- a/lib/data/services/mock_data/tenders_mock_data.dart +++ /dev/null @@ -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 - } - ] -} -'''; diff --git a/lib/data/services/your_tenders_service.dart b/lib/data/services/your_tenders_service.dart index b1e1c54..910cdad 100644 --- a/lib/data/services/your_tenders_service.dart +++ b/lib/data/services/your_tenders_service.dart @@ -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> getApprovedTenders() async { + Future> 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> 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; + } } diff --git a/lib/view_models/your_tenders_view_model.dart b/lib/view_models/your_tenders_view_model.dart index e381234..caf70da 100644 --- a/lib/view_models/your_tenders_view_model.dart +++ b/lib/view_models/your_tenders_view_model.dart @@ -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 getApprovedTenders() async { + Future 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(): @@ -86,6 +102,75 @@ class YourTendersViewModel with ChangeNotifier { notifyListeners(); } + Future 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(): + 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(): + errorMessage = result.error.toString(); + break; + } + + isLoading = false; + isLoadingMore = false; + notifyListeners(); + } + + Future 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 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); } } } diff --git a/lib/views/your_tenders/pages/your_tenders_desktop_page.dart b/lib/views/your_tenders/pages/your_tenders_desktop_page.dart index 0f10819..a0226a3 100644 --- a/lib/views/your_tenders/pages/your_tenders_desktop_page.dart +++ b/lib/views/your_tenders/pages/your_tenders_desktop_page.dart @@ -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 void initState() { super.initState(); controller = TabController(length: 2, vsync: this); - - WidgetsBinding.instance.addPostFrameCallback((_) { - context.read().getApprovedTenders(); - }); } @override @@ -94,9 +92,28 @@ class _YourTendersDesktopPageState extends State if (viewModel.errorMessage != null) { return Center(child: Text(viewModel.errorMessage!)); } - return TendersSubmitted( - approvedTenders: viewModel.data!, - ); + + 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: [ diff --git a/lib/views/your_tenders/pages/your_tenders_mobile_page.dart b/lib/views/your_tenders/pages/your_tenders_mobile_page.dart index 9395b56..d5ed809 100644 --- a/lib/views/your_tenders/pages/your_tenders_mobile_page.dart +++ b/lib/views/your_tenders/pages/your_tenders_mobile_page.dart @@ -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,10 +56,34 @@ class _YourTendersMobilePageState extends State { return Column( children: [ - // Expanded(child: ApprovedTenders(tendersSubmitted: [])), - Expanded( - child: TendersSubmitted(approvedTenders: viewModel.data!), - ), + if (viewModel.selectedStatus == + YourTendersStrings.likeTenders && + viewModel.likedTendersData != null) + Expanded( + 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')), + ), ], ); }, diff --git a/lib/views/your_tenders/pages/your_tenders_tablet_page.dart b/lib/views/your_tenders/pages/your_tenders_tablet_page.dart index 3f9d4e6..93dc429 100644 --- a/lib/views/your_tenders/pages/your_tenders_tablet_page.dart +++ b/lib/views/your_tenders/pages/your_tenders_tablet_page.dart @@ -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 void initState() { super.initState(); controller = TabController(length: 2, vsync: this); - - WidgetsBinding.instance.addPostFrameCallback((_) { - context.read().getApprovedTenders(); - }); } @override @@ -46,10 +43,7 @@ class _YourTendersTabletPageState extends State 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 if (viewModel.errorMessage != null) { return Center(child: Text(viewModel.errorMessage!)); } - return TendersSubmitted(approvedTenders: viewModel.data!); + + 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')); + } }, ), ), diff --git a/lib/views/your_tenders/widgets/liked_disliked_tenders_list.dart b/lib/views/your_tenders/widgets/liked_disliked_tenders_list.dart new file mode 100644 index 0000000..587bac6 --- /dev/null +++ b/lib/views/your_tenders/widgets/liked_disliked_tenders_list.dart @@ -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 createState() => + _LikedDislikedTendersListState(); +} + +class _LikedDislikedTendersListState extends State { + final ScrollController _controller = ScrollController(); + + @override + void initState() { + super.initState(); + _controller.addListener(_onScroll); + } + + void _onScroll() { + final vm = context.read(); + 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(); + 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!, + ), + ); + }, + ); + } +}