diff --git a/lib/core/network/network_manager.dart b/lib/core/network/network_manager.dart index 9832ccb..5f96cab 100644 --- a/lib/core/network/network_manager.dart +++ b/lib/core/network/network_manager.dart @@ -32,7 +32,9 @@ class NetworkManager { } void _addInterceptors() { - if (_interceptorsAdded) return; + if (_interceptorsAdded) { + return; + } final requestInterceptor = InterceptorsWrapper( onRequest: (options, handler) { diff --git a/lib/core/utils/date_utils.dart b/lib/core/utils/date_utils.dart index 13eb8ab..aabdfa9 100644 --- a/lib/core/utils/date_utils.dart +++ b/lib/core/utils/date_utils.dart @@ -3,7 +3,9 @@ import 'package:intl/intl.dart'; class DateUtils { /// Converts Unix timestamp (seconds since epoch) to a formatted date string static String unixToDate(int? unixTimestamp, {String format = 'yyyy-MM-dd'}) { - if (unixTimestamp == null) return ''; + if (unixTimestamp == null) { + return ''; + } // Convert seconds to milliseconds if needed int timestampInMs = @@ -17,7 +19,9 @@ class DateUtils { /// Converts Unix timestamp to a readable date string static String unixToReadableDate(int? unixTimestamp) { - if (unixTimestamp == null) return ''; + if (unixTimestamp == null) { + return ''; + } int timestampInMs = unixTimestamp > 1000000000000 ? unixTimestamp : unixTimestamp * 1000; @@ -41,7 +45,9 @@ class DateUtils { /// Converts Unix timestamp to a short date format static String unixToShortDate(int? unixTimestamp) { - if (unixTimestamp == null) return ''; + if (unixTimestamp == null) { + return ''; + } int timestampInMs = unixTimestamp > 1000000000000 ? unixTimestamp : unixTimestamp * 1000; @@ -54,7 +60,9 @@ class DateUtils { /// Converts Unix timestamp to a full date and time format static String unixToDateTime(int? unixTimestamp) { - if (unixTimestamp == null) return ''; + if (unixTimestamp == null) { + return ''; + } int timestampInMs = unixTimestamp > 1000000000000 ? unixTimestamp : unixTimestamp * 1000; @@ -67,7 +75,9 @@ class DateUtils { /// Checks if a Unix timestamp is in the past static bool isPast(int? unixTimestamp) { - if (unixTimestamp == null) return false; + if (unixTimestamp == null) { + return false; + } int timestampInMs = unixTimestamp > 1000000000000 ? unixTimestamp : unixTimestamp * 1000; @@ -80,7 +90,9 @@ class DateUtils { /// Gets the number of days remaining until a Unix timestamp static int daysRemaining(int? unixTimestamp) { - if (unixTimestamp == null) return 0; + if (unixTimestamp == null) { + return 0; + } int timestampInMs = unixTimestamp > 1000000000000 ? unixTimestamp : unixTimestamp * 1000; diff --git a/lib/data/repositories/auth_repository.dart b/lib/data/repositories/auth_repository.dart index 76acdbb..a931d05 100644 --- a/lib/data/repositories/auth_repository.dart +++ b/lib/data/repositories/auth_repository.dart @@ -1,8 +1,8 @@ import 'package:tm_app/data/services/model/login_response/login_response_model.dart'; -import 'package:tm_app/data/services/model/logout_response/logout_response.dart'; import '../../core/utils/result.dart'; import '../services/auth_service.dart'; +import '../services/model/logout_response/logout_response.dart'; class AuthRepository { final AuthService _authService; diff --git a/lib/data/repositories/home_repository.dart b/lib/data/repositories/home_repository.dart index 2ba1740..3ba476e 100644 --- a/lib/data/repositories/home_repository.dart +++ b/lib/data/repositories/home_repository.dart @@ -1,7 +1,5 @@ import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/data/services/home_service.dart'; -import 'package:tm_app/data/services/model/home/home_request/home_request_model.dart'; -import 'package:tm_app/data/services/model/home/home_response/home_response_model.dart'; import 'package:tm_app/data/services/model/recommended_tenders_response/recommended_tenders_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_state_response/tender_approvals_state_response.dart'; @@ -13,12 +11,6 @@ class HomeRepository { : _homeService = homeService; final HomeService _homeService; - Future> getHome({ - HomeRequestModel? homeRequestModel, - }) async { - return _homeService.getHome(homeRequestModel: homeRequestModel); - } - Future> getHomeRecommendedTenders({ required int limit, required int offset, diff --git a/lib/data/repositories/tenders_repository.dart b/lib/data/repositories/tenders_repository.dart index 8d991ad..a54a1f5 100644 --- a/lib/data/repositories/tenders_repository.dart +++ b/lib/data/repositories/tenders_repository.dart @@ -28,7 +28,7 @@ class TendersRepository { required String tenderId, required String feedbackType, }) async { - return _tendersService.feedback( + return _tendersService.toggleFeedback( tenderId: tenderId, feedbackType: feedbackType, ); diff --git a/lib/data/services/api/auth_api.dart b/lib/data/services/api/auth_api.dart new file mode 100644 index 0000000..bc2a7ba --- /dev/null +++ b/lib/data/services/api/auth_api.dart @@ -0,0 +1,4 @@ +class AuthApi { + static const String login = '/api/v1/profile/login'; + static const String logout = '/api/v1/profile/logout'; +} diff --git a/lib/data/services/api/home_api.dart b/lib/data/services/api/home_api.dart new file mode 100644 index 0000000..c2cab7d --- /dev/null +++ b/lib/data/services/api/home_api.dart @@ -0,0 +1,13 @@ +class HomeApi { + static const String recommendedTenders = '/api/v1/tenders/recommend'; + static String getRecommendedTenders({ + required int limit, + required int offset, + }) { + return '$recommendedTenders?limit=$limit&offset=$offset'; + } + + static const String tenderApprovals = '/api/v1/tender-approvals'; + static const String tenderApprovalStats = '/api/v1/tender-approvals/stats'; + static const String statsCompany = '/api/v1/feedback/stats/company'; +} diff --git a/lib/data/services/api/profile_api.dart b/lib/data/services/api/profile_api.dart new file mode 100644 index 0000000..c6e2336 --- /dev/null +++ b/lib/data/services/api/profile_api.dart @@ -0,0 +1,4 @@ +class ProfileApi { + static const String profile = '/api/v1/profile'; + static const String companyProfile = '/api/v1/companies'; +} diff --git a/lib/data/services/api/tender_detail_api.dart b/lib/data/services/api/tender_detail_api.dart new file mode 100644 index 0000000..90eae52 --- /dev/null +++ b/lib/data/services/api/tender_detail_api.dart @@ -0,0 +1,6 @@ +class TenderDetailApi { + static const String tenderDetails = '/api/v1/tenders/details'; + static String getTenderDetails({required String tenderId}) { + return '$tenderDetails/$tenderId'; + } +} diff --git a/lib/data/services/api/tenders_api.dart b/lib/data/services/api/tenders_api.dart new file mode 100644 index 0000000..facce5d --- /dev/null +++ b/lib/data/services/api/tenders_api.dart @@ -0,0 +1,20 @@ +class TendersApi { + static const String tenders = '/api/v1/tenders'; + static String getTenders({required int limit, required int offset}) { + return '$tenders?limit=$limit&offset=$offset'; + } + + static const String feedbackTender = '/api/v1/feedback/tender'; + static String getFeedbackForTender({required String tenderId}) { + return '$feedbackTender/$tenderId'; + } + + static const String feedback = '/api/v1/feedback'; + + static const String tenderApprovals = '/api/v1/tender-approvals'; + + static const String tenderApprovalsTender = '/api/v1/tender-approvals/tender'; + static String getTenderApprovalById({required String tenderId}) { + return '$tenderApprovalsTender/$tenderId'; + } +} diff --git a/lib/data/services/api/your_tenders_api.dart b/lib/data/services/api/your_tenders_api.dart new file mode 100644 index 0000000..99ad134 --- /dev/null +++ b/lib/data/services/api/your_tenders_api.dart @@ -0,0 +1,4 @@ +class YourTendersApi { + static const String tenderApprovalsStatus = + '/api/v1/tender-approvals?status=submitted'; +} diff --git a/lib/data/services/auth_service.dart b/lib/data/services/auth_service.dart index 9b529d6..66ef13c 100644 --- a/lib/data/services/auth_service.dart +++ b/lib/data/services/auth_service.dart @@ -3,6 +3,8 @@ import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tm_app/core/utils/logger.dart'; +import 'package:tm_app/data/services/api/auth_api.dart'; import 'package:tm_app/data/services/model/login_response/login_response_model.dart'; import 'package:tm_app/data/services/model/logout_response/logout_response.dart'; @@ -22,7 +24,7 @@ class AuthService { var data = jsonEncode({"password": password, "username": username}); final result = await _networkManager.makeRequest( - '/api/v1/profile/login', + AuthApi.login, method: 'POST', (json) => LoginResponseModel.fromJson(json), data: data, @@ -41,7 +43,7 @@ class AuthService { Future> logout() async { final result = await _networkManager.makeRequest( - '/api/v1/profile/logout', + AuthApi.logout, method: 'DELETE', (json) => LogoutResponse.fromJson(json), ); @@ -52,5 +54,6 @@ class AuthService { final prefs = await SharedPreferences.getInstance(); await prefs.remove('bearer'); await prefs.remove('refresh_token'); + appLogger.info('tokens cleared!'); } } diff --git a/lib/data/services/home_service.dart b/lib/data/services/home_service.dart index d3f6658..76f9c71 100644 --- a/lib/data/services/home_service.dart +++ b/lib/data/services/home_service.dart @@ -1,12 +1,6 @@ -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/mock_data/home_mock_data.dart'; +import 'package:tm_app/data/services/api/home_api.dart'; import 'package:tm_app/data/services/model/feedback_stats_response/feedback_stat_response.dart'; -import 'package:tm_app/data/services/model/home/home_request/home_request_model.dart'; -import 'package:tm_app/data/services/model/home/home_response/home_response_model.dart'; import 'package:tm_app/data/services/model/recommended_tenders_response/recommended_tenders_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_state_response/tender_approvals_state_response.dart'; @@ -18,36 +12,12 @@ class HomeService { : _networkManager = networkManager; final NetworkManager _networkManager; - Future> getHome({ - HomeRequestModel? homeRequestModel, - }) async { - try { - // final result = await _networkManager.makeRequest( - // '/api/v1/home', - // (json) => HomeResponseModel.fromJson(json), - // method: 'GET', - // ); - await Future.delayed(Duration(seconds: 2)); - appLogger.info('get home success'); - // TODO: will change when api is ready - return Result.ok( - HomeResponseModel.fromJson(jsonDecode(homeMockData)['data']), - ); - } on DioException catch (e) { - appLogger.error('get home failed: $e'); - return Result.error(e); - } on Exception catch (e, stackTrace) { - appLogger.error('get home failed: $e', stackTrace: stackTrace); - return Result.error(Exception(e)); - } - } - Future> getRecommendedTenders({ required int limit, required int offset, }) async { final result = await _networkManager.makeRequest( - '/api/v1/tenders/recommend?limit=$limit&offset=$offset', + HomeApi.getRecommendedTenders(limit: limit, offset: offset), method: 'GET', (json) => RecommendedTendersResponse.fromJson(json), ); @@ -56,7 +26,7 @@ class HomeService { Future> getYourTenders() async { final result = await _networkManager.makeRequest( - '/api/v1/tender-approvals', + HomeApi.tenderApprovals, (json) => TenderApprovalsResponse.fromJson(json), method: 'GET', ); @@ -67,7 +37,7 @@ class HomeService { Future> getTendersApprovalsState() async { final result = await _networkManager.makeRequest( - '/api/v1/tender-approvals/stats', + HomeApi.tenderApprovalStats, (json) => TenderApprovalsStateResponse.fromJson(json), method: 'GET', ); @@ -77,7 +47,7 @@ class HomeService { Future> getFeedbackStats() async { final result = await _networkManager.makeRequest( - '/api/v1/feedback/stats/company', + HomeApi.statsCompany, (json) => FeedbackStatResponse.fromJson(json), method: 'GET', ); diff --git a/lib/data/services/profile_service.dart b/lib/data/services/profile_service.dart index 58012d5..8e52722 100644 --- a/lib/data/services/profile_service.dart +++ b/lib/data/services/profile_service.dart @@ -1,3 +1,4 @@ +import 'package:tm_app/data/services/api/profile_api.dart'; import 'package:tm_app/data/services/model/company_profile_response/company_profile_response.dart'; import 'package:tm_app/data/services/model/profile_response/profile_response.dart'; @@ -12,7 +13,7 @@ class ProfileService { Future> getProfile() async { final result = await _networkManager.makeRequest( - '/api/v1/profile', + ProfileApi.profile, method: 'GET', (json) => ProfileResponse.fromJson(json), ); @@ -21,7 +22,7 @@ class ProfileService { Future> getCompanyProfile() async { final result = await _networkManager.makeRequest( - '/api/v1/companies', + ProfileApi.companyProfile, method: 'GET', (json) => CompanyProfileResponse.fromJson(json), ); diff --git a/lib/data/services/tender_detail_service.dart b/lib/data/services/tender_detail_service.dart index 4f51543..ab7664b 100644 --- a/lib/data/services/tender_detail_service.dart +++ b/lib/data/services/tender_detail_service.dart @@ -1,4 +1,5 @@ import 'package:tm_app/core/utils/result.dart'; +import 'package:tm_app/data/services/api/tender_detail_api.dart'; import 'package:tm_app/data/services/model/tender_detail_response/tender_detail_response_model.dart'; import '../../core/network/network_manager.dart'; @@ -13,7 +14,7 @@ class TenderDetailService { required String tenderId, }) async { final result = await _networkManager.makeRequest( - '/api/v1/tenders/details/$tenderId', + TenderDetailApi.getTenderDetails(tenderId: tenderId), method: 'GET', (json) => TenderDetailResponseModel.fromJson(json), ); diff --git a/lib/data/services/tenders_service.dart b/lib/data/services/tenders_service.dart index 709c398..216045f 100644 --- a/lib/data/services/tenders_service.dart +++ b/lib/data/services/tenders_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:tm_app/core/utils/result.dart'; +import 'package:tm_app/data/services/api/tenders_api.dart'; import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart'; @@ -18,7 +19,7 @@ class TendersService { required int offset, }) async { final result = await _networkManager.makeRequest( - '/api/v1/tenders?limit=$limit&offset=$offset', + TendersApi.getTenders(limit: limit, offset: offset), method: 'GET', (json) => TendersResponse.fromJson(json), ); @@ -29,14 +30,14 @@ class TendersService { required String tenderId, }) async { final result = await _networkManager.makeRequest( - '/api/v1/feedback/tender/$tenderId', + TendersApi.getFeedbackForTender(tenderId: tenderId), method: 'GET', (json) => FeedbackResponse.fromJson(json), ); return result; } - Future> feedback({ + Future> toggleFeedback({ required String tenderId, required String feedbackType, }) async { @@ -45,7 +46,7 @@ class TendersService { 'tender_id': tenderId, }); final result = await _networkManager.makeRequest( - '/api/v1/feedback', + TendersApi.feedback, method: 'POST', (json) => FeedbackResponse.fromJson(json), data: data, @@ -64,7 +65,7 @@ class TendersService { 'status': status, }); final result = await _networkManager.makeRequest( - '/api/v1/tender-approvals', + TendersApi.tenderApprovals, method: 'POST', (json) => TenderApprovalsToggleResponse.fromJson(json), data: data, @@ -76,7 +77,7 @@ class TendersService { required String tenderId, }) async { final result = await _networkManager.makeRequest( - '/api/v1/tender-approvals/tender/$tenderId', + TendersApi.getTenderApprovalById(tenderId: tenderId), method: 'GET', (json) => TenderApprovalsByIdResponse.fromJson(json), ); diff --git a/lib/data/services/your_tenders_service.dart b/lib/data/services/your_tenders_service.dart index c7ec695..bb36bbe 100644 --- a/lib/data/services/your_tenders_service.dart +++ b/lib/data/services/your_tenders_service.dart @@ -1,6 +1,5 @@ -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/api/your_tenders_api.dart'; import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart'; import '../../../core/network/network_manager.dart'; @@ -12,23 +11,12 @@ class YourTendersService { final NetworkManager _networkManager; Future> getApprovedTenders() async { - try { - final result = await _networkManager.makeRequest( - '/api/v1/tender-approvals?status=submitted', - (json) => TenderApprovalsResponse.fromJson(json), - method: 'GET', - ); + final result = await _networkManager.makeRequest( + YourTendersApi.tenderApprovalsStatus, + (json) => TenderApprovalsResponse.fromJson(json), + method: 'GET', + ); - return result; - } on DioException catch (e) { - appLogger.error('get submitted tenders failed: $e'); - return Result.error(e); - } on Exception catch (e, stackTrace) { - appLogger.error( - 'get submitted tenders failed: $e', - stackTrace: stackTrace, - ); - return Result.error(Exception(e)); - } + return result; } } diff --git a/lib/view_models/home_view_model.dart b/lib/view_models/home_view_model.dart index 0f2fa3a..cc947f2 100644 --- a/lib/view_models/home_view_model.dart +++ b/lib/view_models/home_view_model.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/data/services/model/feedback_stats/feedback_stats.dart'; -import 'package:tm_app/data/services/model/home/home_request/home_request_model.dart'; import 'package:tm_app/data/services/model/recommended_tenders_response/recommended_tenders_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_state_response/tender_approvals_state_response.dart'; @@ -51,30 +50,10 @@ class HomeViewModel with ChangeNotifier { await getFeedbackStats(); } - Future getHome({HomeRequestModel? homeRequestModel}) async { - _isLoading = true; - _errorMessage = null; - notifyListeners(); - - final result = await _homeRepository.getHome( - homeRequestModel: homeRequestModel, - ); - - switch (result) { - case Ok(): - _homeResponse = result.value; - break; - case Error(): - _errorMessage = result.error.toString(); - break; - } - - _isLoading = false; - notifyListeners(); - } - Future getHomeRecommandTenders({bool reset = false}) async { - if (_isLoadingMore || (!_hasMore && !reset)) return; + if (_isLoadingMore || (!_hasMore && !reset)) { + return; + } if (reset) { _currentPage = 0; diff --git a/lib/view_models/tenders_view_model.dart b/lib/view_models/tenders_view_model.dart index c954e8f..af0a25a 100644 --- a/lib/view_models/tenders_view_model.dart +++ b/lib/view_models/tenders_view_model.dart @@ -122,7 +122,9 @@ class TendersViewModel with ChangeNotifier { } Future loadMoreTenders() async { - if (_isLoadingMore || !_hasMoreData) return; + if (_isLoadingMore || !_hasMoreData) { + return; + } _isLoadingMore = true; _errorMessage = null; diff --git a/lib/views/detail/widgets/tender_detail_header.dart b/lib/views/detail/widgets/tender_detail_header.dart index a216068..b38abab 100644 --- a/lib/views/detail/widgets/tender_detail_header.dart +++ b/lib/views/detail/widgets/tender_detail_header.dart @@ -75,7 +75,9 @@ class TenderDetailHeader extends StatelessWidget { } String unixToDate(int? unixTimestamp, {String format = 'yyyy-MM-dd'}) { - if (unixTimestamp == null) return ''; + if (unixTimestamp == null) { + return ''; + } // Convert seconds to milliseconds if needed int timestampInMs =