diff --git a/lib/data/repositories/your_tenders_repository.dart b/lib/data/repositories/your_tenders_repository.dart index 007d5f7..7432d78 100644 --- a/lib/data/repositories/your_tenders_repository.dart +++ b/lib/data/repositories/your_tenders_repository.dart @@ -3,10 +3,25 @@ import 'package:tm_app/data/services/model/tender_approvals_response/tender_appr import 'package:tm_app/data/services/your_tenders_service.dart'; class YourTendersRepository { - final YourTendersService yourTendersService; - YourTendersRepository({required this.yourTendersService}); + final YourTendersService _yourTendersService; + YourTendersRepository({required YourTendersService yourTendersService}) + : _yourTendersService = yourTendersService; Future> getApprovedTenders() { - return yourTendersService.getApprovedTenders(); + return _yourTendersService.getApprovedTenders(); + } + + Future> getTenders({ + required int limit, + required int offset, + required String createdFrom, + required String createdTo, + }) { + return _yourTendersService.getTenders( + limit: limit, + offset: offset, + createdFrom: createdFrom, + createdTo: createdTo, + ); } } diff --git a/lib/data/services/api/your_tenders_api.dart b/lib/data/services/api/your_tenders_api.dart index 99ad134..ff30be2 100644 --- a/lib/data/services/api/your_tenders_api.dart +++ b/lib/data/services/api/your_tenders_api.dart @@ -1,4 +1,18 @@ class YourTendersApi { static const String tenderApprovalsStatus = '/api/v1/tender-approvals?status=submitted'; + + static const String tenderApproval = '/api/v1/tender-approvals'; + + static String getTenders({ + required int limit, + required int offset, + required String createdFrom, + required String createdTo, + }) { + if (createdFrom.isNotEmpty && createdTo.isNotEmpty) { + return '$tenderApproval?limit=$limit&offset=$offset&created_from=$createdFrom&created_to=$createdTo'; + } + return '$tenderApproval?limit=$limit&offset=$offset'; + } } diff --git a/lib/data/services/your_tenders_service.dart b/lib/data/services/your_tenders_service.dart index bb36bbe..b1e1c54 100644 --- a/lib/data/services/your_tenders_service.dart +++ b/lib/data/services/your_tenders_service.dart @@ -19,4 +19,23 @@ class YourTendersService { return result; } + + Future> getTenders({ + required int limit, + required int offset, + required String createdFrom, + required String createdTo, + }) async { + final result = await _networkManager.makeRequest( + YourTendersApi.getTenders( + limit: limit, + offset: offset, + createdFrom: createdFrom, + createdTo: createdTo, + ), + (json) => TenderApprovalsResponse.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 fb49e5e..e381234 100644 --- a/lib/view_models/your_tenders_view_model.dart +++ b/lib/view_models/your_tenders_view_model.dart @@ -6,9 +6,7 @@ import 'package:tm_app/data/services/model/tender_approvals_response/tender_appr class YourTendersViewModel with ChangeNotifier { final YourTendersRepository yourTendersRepository; - YourTendersViewModel({required this.yourTendersRepository}) { - getApprovedTenders(); - } + YourTendersViewModel({required this.yourTendersRepository}); bool isLoading = false; String? errorMessage; @@ -20,10 +18,24 @@ class YourTendersViewModel with ChangeNotifier { final _fmt = DateFormat('yyyy/MM/dd'); String get startDateFormatted => - selectedDateRange?.start != null ? _fmt.format(selectedDateRange!.start) : 'YYYY/MM/DD'; + selectedDateRange?.start != null + ? _fmt.format(selectedDateRange!.start) + : 'YYYY/MM/DD'; String get endDateFormatted => - selectedDateRange?.end != null ? _fmt.format(selectedDateRange!.end) : 'YYYY/MM/DD'; + selectedDateRange?.end != null + ? _fmt.format(selectedDateRange!.end) + : 'YYYY/MM/DD'; + + int get startDateUnix => + selectedDateRange?.start != null + ? selectedDateRange!.start.millisecondsSinceEpoch ~/ 1000 + : 0; + + int get endDateUnix => + selectedDateRange?.end != null + ? selectedDateRange!.end.millisecondsSinceEpoch ~/ 1000 + : 0; Future getApprovedTenders() async { isLoading = true; @@ -45,6 +57,35 @@ class YourTendersViewModel with ChangeNotifier { notifyListeners(); } + Future getTenders({ + required int limit, + required int offset, + required String createdFrom, + required String createdTo, + }) async { + isLoading = true; + notifyListeners(); + + final result = await yourTendersRepository.getTenders( + limit: limit, + offset: offset, + createdFrom: createdFrom, + createdTo: createdTo, + ); + switch (result) { + case Ok(): + data = result.value; + errorMessage = null; + break; + case Error(): + errorMessage = result.error.toString(); + break; + } + + isLoading = false; + notifyListeners(); + } + // --- Filter Actions --- void setDateRange(DateTimeRange? range) { selectedDateRange = range; @@ -55,4 +96,23 @@ class YourTendersViewModel with ChangeNotifier { selectedStatus = status; notifyListeners(); } + + void clearFilter() { + selectedDateRange = null; + selectedStatus = 'All'; + notifyListeners(); + } + + Future callWithFilter() async { + if (selectedStatus == 'All') { + await getTenders( + limit: 10, + offset: 0, + createdFrom: startDateUnix.toString(), + createdTo: endDateUnix.toString(), + ); + } else if (selectedStatus == 'Tenders submitted') { + await getApprovedTenders(); + } + } } diff --git a/lib/views/tenders/widgets/tender_card.dart b/lib/views/tenders/widgets/tender_card.dart index 13f5ce9..4b366f8 100644 --- a/lib/views/tenders/widgets/tender_card.dart +++ b/lib/views/tenders/widgets/tender_card.dart @@ -169,7 +169,8 @@ class TenderCard extends StatelessWidget { Widget _tenderDescription() { return Text( tender.description ?? '', - maxLines: 7, + maxLines: 4, + overflow: TextOverflow.ellipsis, style: TextStyle( color: AppColors.grey70, fontSize: 16.0.sp(), 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 858f193..9395b56 100644 --- a/lib/views/your_tenders/pages/your_tenders_mobile_page.dart +++ b/lib/views/your_tenders/pages/your_tenders_mobile_page.dart @@ -7,9 +7,29 @@ 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/tenders_submitted.dart'; -class YourTendersMobilePage extends StatelessWidget { +class YourTendersMobilePage extends StatefulWidget { const YourTendersMobilePage({super.key}); + @override + State createState() => _YourTendersMobilePageState(); +} + +class _YourTendersMobilePageState extends State { + late final YourTendersViewModel viewModel; + @override + void initState() { + viewModel = context.read(); + super.initState(); + } + + @override + void dispose() { + WidgetsBinding.instance.addPostFrameCallback((_) { + viewModel.clearFilter(); + }); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/views/your_tenders/pages/your_tenders_screen.dart b/lib/views/your_tenders/pages/your_tenders_screen.dart index 2554d3e..fbe2ecb 100644 --- a/lib/views/your_tenders/pages/your_tenders_screen.dart +++ b/lib/views/your_tenders/pages/your_tenders_screen.dart @@ -1,13 +1,35 @@ import 'package:flutter/material.dart'; -import 'package:tm_app/core/utils/size_config.dart'; +import 'package:provider/provider.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/shared/responsive_builder.dart'; import 'package:tm_app/views/your_tenders/pages/your_tenders_desktop_page.dart'; import 'package:tm_app/views/your_tenders/pages/your_tenders_mobile_page.dart'; import 'package:tm_app/views/your_tenders/pages/your_tenders_tablet_page.dart'; -class YourTendersScreen extends StatelessWidget { +class YourTendersScreen extends StatefulWidget { const YourTendersScreen({super.key}); + @override + State createState() => _YourTendersScreenState(); +} + +class _YourTendersScreenState extends State { + late final YourTendersViewModel viewModel; + @override + void initState() { + super.initState(); + viewModel = context.read(); + WidgetsBinding.instance.addPostFrameCallback((_) { + viewModel.getTenders( + limit: 10, + offset: 0, + createdFrom: '', + createdTo: '', + ); + }); + } + @override Widget build(BuildContext context) { SizeConfig.init(context); diff --git a/lib/views/your_tenders/widgets/tender_card.dart b/lib/views/your_tenders/widgets/tender_card.dart index c8dee35..8beade1 100644 --- a/lib/views/your_tenders/widgets/tender_card.dart +++ b/lib/views/your_tenders/widgets/tender_card.dart @@ -1,6 +1,7 @@ import 'package:country_flags/country_flags.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:tm_app/core/utils/date_utils.dart'; import '../../../core/constants/assets.dart'; import '../../../core/theme/colors.dart'; @@ -63,7 +64,7 @@ class TenderCard extends StatelessWidget { children: [ // Date Text( - date, + unixToDate(int.parse(date)), style: TextStyle( color: AppColors.grey60, fontSize: 12.0.sp(), diff --git a/lib/views/your_tenders/widgets/tenders_filter_dialog.dart b/lib/views/your_tenders/widgets/tenders_filter_dialog.dart index c3de0d8..a0aa696 100644 --- a/lib/views/your_tenders/widgets/tenders_filter_dialog.dart +++ b/lib/views/your_tenders/widgets/tenders_filter_dialog.dart @@ -64,7 +64,9 @@ class TendersFilterDialog extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - start == null ? YourTendersStrings.startDate : viewModel.startDateFormatted, + start == null + ? YourTendersStrings.startDate + : viewModel.startDateFormatted, style: TextStyle( fontSize: 16.0.sp(), fontWeight: FontWeight.w400, @@ -72,7 +74,9 @@ class TendersFilterDialog extends StatelessWidget { ), ), Text( - end == null ? YourTendersStrings.endDate : viewModel.endDateFormatted, + end == null + ? YourTendersStrings.endDate + : viewModel.endDateFormatted, style: TextStyle( fontSize: 16.0.sp(), fontWeight: FontWeight.w400, @@ -158,6 +162,7 @@ class TendersFilterDialog extends StatelessWidget { isEnabled: true, onPressed: () { context.pop(); + vm.callWithFilter(); }, text: YourTendersStrings.confirm, textColor: AppColors.mainBlue,