From 376b4e4431b050f0073166dd966f91b979e7052c Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 17 Mar 2026 12:01:06 -0400 Subject: [PATCH] feat: Update API endpoint usage in repositories to remove redundant path property - Refactored multiple repository implementations across client and staff features to directly use endpoint objects without accessing the `path` property. - Introduced a new `FeatureGate` class for client-side feature gating based on user scopes, allowing for better access control to API endpoints. - Added `ApiEndpoint` class to represent API endpoints with their paths and required scopes for future feature gating. --- apps/mobile/packages/core/lib/core.dart | 4 +- .../src/services/api_service/api_service.dart | 34 +++++---- .../file_upload/file_upload_service.dart | 2 +- .../core_api_services/llm/llm_service.dart | 2 +- .../rapid_order/rapid_order_service.dart | 4 +- .../signed_url/signed_url_service.dart | 2 +- .../verification/verification_service.dart | 8 +-- .../api_service/endpoints/auth_endpoints.dart | 2 +- .../endpoints/client_endpoints.dart | 2 +- .../api_service/endpoints/core_endpoints.dart | 2 +- .../endpoints/staff_endpoints.dart | 2 +- .../services/api_service/feature_gate.dart | 69 +++++++++++++++++++ .../services/session/v2_session_service.dart | 4 +- .../packages/domain/lib/krow_domain.dart | 1 + .../services/api_services}/api_endpoint.dart | 0 .../api_services/base_api_service.dart | 14 ++-- .../lib/src/exceptions/app_exception.dart | 19 +++++ .../auth_repository_impl.dart | 6 +- .../billing_repository_impl.dart | 16 ++--- .../coverage_repository_impl.dart | 8 +-- .../home_repository_impl.dart | 4 +- .../hub_repository_impl.dart | 16 ++--- .../client_create_order_repository_impl.dart | 8 +-- .../client_order_query_repository_impl.dart | 8 +-- .../view_orders_repository_impl.dart | 14 ++-- .../reports_repository_impl.dart | 14 ++-- .../settings_repository_impl.dart | 2 +- .../auth_repository_impl.dart | 6 +- .../profile_setup_repository_impl.dart | 2 +- .../availability_repository_impl.dart | 6 +- .../clock_in_repository_impl.dart | 8 +-- .../repositories/home_repository_impl.dart | 4 +- .../payments_repository_impl.dart | 6 +- .../repositories/profile_repository_impl.dart | 6 +- .../certificates_repository_impl.dart | 6 +- .../documents_repository_impl.dart | 4 +- .../tax_forms_repository_impl.dart | 6 +- .../bank_account_repository_impl.dart | 4 +- .../time_card_repository_impl.dart | 2 +- .../attire_repository_impl.dart | 4 +- .../emergency_contact_repository_impl.dart | 4 +- .../experience_repository_impl.dart | 6 +- .../personal_info_repository_impl.dart | 6 +- .../faqs_repository_impl.dart | 4 +- .../privacy_settings_repository_impl.dart | 4 +- .../shifts_repository_impl.dart | 22 +++--- .../staff_main_repository_impl.dart | 2 +- 47 files changed, 240 insertions(+), 139 deletions(-) create mode 100644 apps/mobile/packages/core/lib/src/services/api_service/feature_gate.dart rename apps/mobile/packages/{core/lib/src/services/api_service => domain/lib/src/core/services/api_services}/api_endpoint.dart (100%) diff --git a/apps/mobile/packages/core/lib/core.dart b/apps/mobile/packages/core/lib/core.dart index 129afe0a..f9143b60 100644 --- a/apps/mobile/packages/core/lib/core.dart +++ b/apps/mobile/packages/core/lib/core.dart @@ -20,8 +20,8 @@ export 'src/services/api_service/dio_client.dart'; export 'src/services/api_service/mixins/api_error_handler.dart'; export 'src/services/api_service/mixins/session_handler_mixin.dart'; -// API Endpoint classes -export 'src/services/api_service/api_endpoint.dart'; +// Feature Gate & Endpoint classes +export 'src/services/api_service/feature_gate.dart'; export 'src/services/api_service/endpoints/auth_endpoints.dart'; export 'src/services/api_service/endpoints/client_endpoints.dart'; export 'src/services/api_service/endpoints/core_endpoints.dart'; diff --git a/apps/mobile/packages/core/lib/src/services/api_service/api_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/api_service.dart index 00c58020..80e7a86b 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/api_service.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/api_service.dart @@ -1,10 +1,11 @@ import 'package:dio/dio.dart'; import 'package:krow_domain/krow_domain.dart'; +import 'feature_gate.dart'; + /// A service that handles HTTP communication using the [Dio] client. /// -/// This class provides a wrapper around [Dio]'s methods to handle -/// response parsing and error handling in a consistent way. +/// Integrates [FeatureGate] to validate endpoint scopes before each request. class ApiService implements BaseApiService { /// Creates an [ApiService] with the given [Dio] instance. ApiService(this._dio); @@ -15,12 +16,13 @@ class ApiService implements BaseApiService { /// Performs a GET request to the specified [endpoint]. @override Future get( - String endpoint, { + ApiEndpoint endpoint, { Map? params, }) async { + FeatureGate.instance.validateAccess(endpoint); try { final Response response = await _dio.get( - endpoint, + endpoint.path, queryParameters: params, ); return _handleResponse(response); @@ -32,13 +34,14 @@ class ApiService implements BaseApiService { /// Performs a POST request to the specified [endpoint]. @override Future post( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }) async { + FeatureGate.instance.validateAccess(endpoint); try { final Response response = await _dio.post( - endpoint, + endpoint.path, data: data, queryParameters: params, ); @@ -51,13 +54,14 @@ class ApiService implements BaseApiService { /// Performs a PUT request to the specified [endpoint]. @override Future put( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }) async { + FeatureGate.instance.validateAccess(endpoint); try { final Response response = await _dio.put( - endpoint, + endpoint.path, data: data, queryParameters: params, ); @@ -70,13 +74,14 @@ class ApiService implements BaseApiService { /// Performs a PATCH request to the specified [endpoint]. @override Future patch( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }) async { + FeatureGate.instance.validateAccess(endpoint); try { final Response response = await _dio.patch( - endpoint, + endpoint.path, data: data, queryParameters: params, ); @@ -89,13 +94,14 @@ class ApiService implements BaseApiService { /// Performs a DELETE request to the specified [endpoint]. @override Future delete( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }) async { + FeatureGate.instance.validateAccess(endpoint); try { final Response response = await _dio.delete( - endpoint, + endpoint.path, data: data, queryParameters: params, ); @@ -105,6 +111,10 @@ class ApiService implements BaseApiService { } } + // --------------------------------------------------------------------------- + // Response handling + // --------------------------------------------------------------------------- + /// Extracts [ApiResponse] from a successful [Response]. ApiResponse _handleResponse(Response response) { return ApiResponse( diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/file_upload/file_upload_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/file_upload/file_upload_service.dart index 84ffd05f..b4231174 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/file_upload/file_upload_service.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/file_upload/file_upload_service.dart @@ -26,7 +26,7 @@ class FileUploadService extends BaseCoreService { if (category != null) 'category': category, }); - return api.post(CoreEndpoints.uploadFile.path, data: formData); + return api.post(CoreEndpoints.uploadFile, data: formData); }); if (res.code.startsWith('2')) { diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/llm/llm_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/llm/llm_service.dart index db5ab3a7..e1670dfc 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/llm/llm_service.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/llm/llm_service.dart @@ -19,7 +19,7 @@ class LlmService extends BaseCoreService { }) async { final ApiResponse res = await action(() async { return api.post( - CoreEndpoints.invokeLlm.path, + CoreEndpoints.invokeLlm, data: { 'prompt': prompt, if (responseJsonSchema != null) diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart index 92e8d249..ba37a20d 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart @@ -19,7 +19,7 @@ class RapidOrderService extends BaseCoreService { }) async { final ApiResponse res = await action(() async { return api.post( - CoreEndpoints.transcribeRapidOrder.path, + CoreEndpoints.transcribeRapidOrder, data: { 'audioFileUri': audioFileUri, 'locale': locale, @@ -51,7 +51,7 @@ class RapidOrderService extends BaseCoreService { }) async { final ApiResponse res = await action(() async { return api.post( - CoreEndpoints.parseRapidOrder.path, + CoreEndpoints.parseRapidOrder, data: { 'text': text, 'locale': locale, diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/signed_url/signed_url_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/signed_url/signed_url_service.dart index 24af5336..a7a5a17d 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/signed_url/signed_url_service.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/signed_url/signed_url_service.dart @@ -17,7 +17,7 @@ class SignedUrlService extends BaseCoreService { }) async { final ApiResponse res = await action(() async { return api.post( - CoreEndpoints.createSignedUrl.path, + CoreEndpoints.createSignedUrl, data: { 'fileUri': fileUri, 'expiresInSeconds': expiresInSeconds, diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/verification/verification_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/verification/verification_service.dart index db35f5dc..bd28e27f 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/verification/verification_service.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/verification/verification_service.dart @@ -22,7 +22,7 @@ class VerificationService extends BaseCoreService { }) async { final ApiResponse res = await action(() async { return api.post( - CoreEndpoints.verifications.path, + CoreEndpoints.verifications, data: { 'type': type, 'subjectType': subjectType, @@ -44,7 +44,7 @@ class VerificationService extends BaseCoreService { /// Polls the status of a specific verification. Future getStatus(String verificationId) async { final ApiResponse res = await action(() async { - return api.get(CoreEndpoints.verificationStatus(verificationId).path); + return api.get(CoreEndpoints.verificationStatus(verificationId)); }); if (res.code.startsWith('2')) { @@ -65,7 +65,7 @@ class VerificationService extends BaseCoreService { }) async { final ApiResponse res = await action(() async { return api.post( - CoreEndpoints.verificationReview(verificationId).path, + CoreEndpoints.verificationReview(verificationId), data: { 'decision': decision, if (note != null) 'note': note, @@ -84,7 +84,7 @@ class VerificationService extends BaseCoreService { /// Retries a verification job that failed or needs re-processing. Future retryVerification(String verificationId) async { final ApiResponse res = await action(() async { - return api.post(CoreEndpoints.verificationRetry(verificationId).path); + return api.post(CoreEndpoints.verificationRetry(verificationId)); }); if (res.code.startsWith('2')) { diff --git a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/auth_endpoints.dart b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/auth_endpoints.dart index 3dd0e56c..ed63b510 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/auth_endpoints.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/auth_endpoints.dart @@ -1,4 +1,4 @@ -import 'package:krow_core/src/services/api_service/api_endpoint.dart'; +import 'package:krow_domain/krow_domain.dart' show ApiEndpoint; /// Authentication endpoints for both staff and client apps. abstract final class AuthEndpoints { diff --git a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/client_endpoints.dart b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/client_endpoints.dart index b72cd7b1..714172bb 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/client_endpoints.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/client_endpoints.dart @@ -1,4 +1,4 @@ -import 'package:krow_core/src/services/api_service/api_endpoint.dart'; +import 'package:krow_domain/krow_domain.dart' show ApiEndpoint; /// Client-specific API endpoints (read and write). abstract final class ClientEndpoints { diff --git a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/core_endpoints.dart b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/core_endpoints.dart index 22b59769..8c18a244 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/core_endpoints.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/core_endpoints.dart @@ -1,4 +1,4 @@ -import 'package:krow_core/src/services/api_service/api_endpoint.dart'; +import 'package:krow_domain/krow_domain.dart' show ApiEndpoint; /// Core infrastructure endpoints (upload, signed URLs, LLM, verifications, /// rapid orders). diff --git a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/staff_endpoints.dart b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/staff_endpoints.dart index b12db827..878c3708 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/endpoints/staff_endpoints.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/endpoints/staff_endpoints.dart @@ -1,4 +1,4 @@ -import 'package:krow_core/src/services/api_service/api_endpoint.dart'; +import 'package:krow_domain/krow_domain.dart' show ApiEndpoint; /// Staff-specific API endpoints (read and write). abstract final class StaffEndpoints { diff --git a/apps/mobile/packages/core/lib/src/services/api_service/feature_gate.dart b/apps/mobile/packages/core/lib/src/services/api_service/feature_gate.dart new file mode 100644 index 00000000..340577a8 --- /dev/null +++ b/apps/mobile/packages/core/lib/src/services/api_service/feature_gate.dart @@ -0,0 +1,69 @@ +import 'package:flutter/foundation.dart'; +import 'package:krow_domain/krow_domain.dart'; + +/// Client-side feature gate that checks user scopes against endpoint +/// requirements before allowing an API call. +/// +/// Usage: +/// ```dart +/// FeatureGate.instance.validateAccess(StaffEndpoints.dashboard); +/// ``` +/// +/// When an endpoint's [ApiEndpoint.requiredScopes] is empty, access is always +/// granted. When scopes are defined, the gate verifies that the user has ALL +/// required scopes. Throws [InsufficientScopeException] if any are missing. +class FeatureGate { + FeatureGate._(); + + /// The global singleton instance. + static final FeatureGate instance = FeatureGate._(); + + /// The scopes the current user has. + List _userScopes = const []; + + /// Updates the user's scopes (call after sign-in or session hydration). + void setUserScopes(List scopes) { + _userScopes = List.unmodifiable(scopes); + debugPrint('[FeatureGate] User scopes updated: $_userScopes'); + } + + /// Clears the user's scopes (call on sign-out). + void clearScopes() { + _userScopes = const []; + debugPrint('[FeatureGate] User scopes cleared'); + } + + /// The current user's scopes (read-only). + List get userScopes => _userScopes; + + /// Returns `true` if the user has all scopes required by [endpoint]. + bool hasAccess(ApiEndpoint endpoint) { + if (endpoint.requiredScopes.isEmpty) return true; + return endpoint.requiredScopes.every( + (String scope) => _userScopes.contains(scope), + ); + } + + /// Validates that the user can access [endpoint]. + /// + /// No-op when the endpoint has no required scopes (ungated). + /// Throws [InsufficientScopeException] when scopes are missing. + void validateAccess(ApiEndpoint endpoint) { + if (endpoint.requiredScopes.isEmpty) return; + + final List missingScopes = endpoint.requiredScopes + .where((String scope) => !_userScopes.contains(scope)) + .toList(); + + if (missingScopes.isNotEmpty) { + throw InsufficientScopeException( + requiredScopes: endpoint.requiredScopes, + userScopes: _userScopes, + technicalMessage: + 'Endpoint "${endpoint.path}" requires scopes ' + '${endpoint.requiredScopes} but user has $_userScopes. ' + 'Missing: $missingScopes', + ); + } + } +} diff --git a/apps/mobile/packages/core/lib/src/services/session/v2_session_service.dart b/apps/mobile/packages/core/lib/src/services/session/v2_session_service.dart index 28881cf8..30b7ce94 100644 --- a/apps/mobile/packages/core/lib/src/services/session/v2_session_service.dart +++ b/apps/mobile/packages/core/lib/src/services/session/v2_session_service.dart @@ -51,7 +51,7 @@ class V2SessionService with SessionHandlerMixin { return null; } - final ApiResponse response = await api.get(AuthEndpoints.session.path); + final ApiResponse response = await api.get(AuthEndpoints.session); if (response.data is Map) { final Map data = @@ -99,7 +99,7 @@ class V2SessionService with SessionHandlerMixin { final BaseApiService? api = _apiService; if (api != null) { try { - await api.post(AuthEndpoints.signOut.path); + await api.post(AuthEndpoints.signOut); } catch (e) { debugPrint('[V2SessionService] Server sign-out failed: $e'); } diff --git a/apps/mobile/packages/domain/lib/krow_domain.dart b/apps/mobile/packages/domain/lib/krow_domain.dart index efe8328e..d848a73b 100644 --- a/apps/mobile/packages/domain/lib/krow_domain.dart +++ b/apps/mobile/packages/domain/lib/krow_domain.dart @@ -23,6 +23,7 @@ export 'src/entities/enums/staff_status.dart'; export 'src/entities/enums/user_role.dart'; // Core +export 'src/core/services/api_services/api_endpoint.dart'; export 'src/core/services/api_services/api_response.dart'; export 'src/core/services/api_services/base_api_service.dart'; export 'src/core/services/api_services/base_core_service.dart'; diff --git a/apps/mobile/packages/core/lib/src/services/api_service/api_endpoint.dart b/apps/mobile/packages/domain/lib/src/core/services/api_services/api_endpoint.dart similarity index 100% rename from apps/mobile/packages/core/lib/src/services/api_service/api_endpoint.dart rename to apps/mobile/packages/domain/lib/src/core/services/api_services/api_endpoint.dart diff --git a/apps/mobile/packages/domain/lib/src/core/services/api_services/base_api_service.dart b/apps/mobile/packages/domain/lib/src/core/services/api_services/base_api_service.dart index a3dabfb0..ab572023 100644 --- a/apps/mobile/packages/domain/lib/src/core/services/api_services/base_api_service.dart +++ b/apps/mobile/packages/domain/lib/src/core/services/api_services/base_api_service.dart @@ -1,36 +1,38 @@ +import 'api_endpoint.dart'; import 'api_response.dart'; /// Abstract base class for API services. /// -/// This defines the contract for making HTTP requests. +/// Methods accept [ApiEndpoint] which carries the path and required scopes. +/// Implementations should validate scopes via [FeatureGate] before executing. abstract class BaseApiService { /// Performs a GET request to the specified [endpoint]. - Future get(String endpoint, {Map? params}); + Future get(ApiEndpoint endpoint, {Map? params}); /// Performs a POST request to the specified [endpoint]. Future post( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }); /// Performs a PUT request to the specified [endpoint]. Future put( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }); /// Performs a PATCH request to the specified [endpoint]. Future patch( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }); /// Performs a DELETE request to the specified [endpoint]. Future delete( - String endpoint, { + ApiEndpoint endpoint, { dynamic data, Map? params, }); diff --git a/apps/mobile/packages/domain/lib/src/exceptions/app_exception.dart b/apps/mobile/packages/domain/lib/src/exceptions/app_exception.dart index a70e2bf6..f8abd5c0 100644 --- a/apps/mobile/packages/domain/lib/src/exceptions/app_exception.dart +++ b/apps/mobile/packages/domain/lib/src/exceptions/app_exception.dart @@ -330,3 +330,22 @@ class NotAuthenticatedException extends AppException { @override String get messageKey => 'errors.auth.not_authenticated'; } + +/// Thrown when the user lacks the required scopes to access an endpoint. +class InsufficientScopeException extends AppException { + /// Creates an [InsufficientScopeException]. + const InsufficientScopeException({ + required this.requiredScopes, + required this.userScopes, + super.technicalMessage, + }) : super(code: 'SCOPE_001'); + + /// The scopes required by the endpoint. + final List requiredScopes; + + /// The scopes the user currently has. + final List userScopes; + + @override + String get messageKey => 'errors.generic.insufficient_scope'; +} diff --git a/apps/mobile/packages/features/client/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart b/apps/mobile/packages/features/client/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart index b1f85552..08185e59 100644 --- a/apps/mobile/packages/features/client/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart +++ b/apps/mobile/packages/features/client/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart @@ -45,7 +45,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface { // Step 1: Call V2 sign-in endpoint — server handles Firebase Auth // via Identity Toolkit and returns a full auth envelope. final ApiResponse response = await _apiService.post( - AuthEndpoints.clientSignIn.path, + AuthEndpoints.clientSignIn, data: { 'email': email, 'password': password, @@ -107,7 +107,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface { // - Creates user, tenant, business, memberships in one transaction // - Returns full auth envelope with session tokens final ApiResponse response = await _apiService.post( - AuthEndpoints.clientSignUp.path, + AuthEndpoints.clientSignUp, data: { 'companyName': companyName, 'email': email, @@ -172,7 +172,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface { Future signOut() async { try { // Step 1: Call V2 sign-out endpoint for server-side token revocation. - await _apiService.post(AuthEndpoints.clientSignOut.path); + await _apiService.post(AuthEndpoints.clientSignOut); } catch (e) { developer.log( 'V2 sign-out request failed: $e', diff --git a/apps/mobile/packages/features/client/billing/lib/src/data/repositories_impl/billing_repository_impl.dart b/apps/mobile/packages/features/client/billing/lib/src/data/repositories_impl/billing_repository_impl.dart index ac5b928b..64027bd7 100644 --- a/apps/mobile/packages/features/client/billing/lib/src/data/repositories_impl/billing_repository_impl.dart +++ b/apps/mobile/packages/features/client/billing/lib/src/data/repositories_impl/billing_repository_impl.dart @@ -17,7 +17,7 @@ class BillingRepositoryImpl implements BillingRepository { @override Future> getBankAccounts() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.billingAccounts.path); + await _apiService.get(ClientEndpoints.billingAccounts); final List items = (response.data as Map)['items'] as List; return items @@ -29,7 +29,7 @@ class BillingRepositoryImpl implements BillingRepository { @override Future> getPendingInvoices() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.billingInvoicesPending.path); + await _apiService.get(ClientEndpoints.billingInvoicesPending); final List items = (response.data as Map)['items'] as List; return items @@ -41,7 +41,7 @@ class BillingRepositoryImpl implements BillingRepository { @override Future> getInvoiceHistory() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.billingInvoicesHistory.path); + await _apiService.get(ClientEndpoints.billingInvoicesHistory); final List items = (response.data as Map)['items'] as List; return items @@ -53,7 +53,7 @@ class BillingRepositoryImpl implements BillingRepository { @override Future getCurrentBillCents() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.billingCurrentBill.path); + await _apiService.get(ClientEndpoints.billingCurrentBill); final Map data = response.data as Map; return (data['currentBillCents'] as num).toInt(); @@ -62,7 +62,7 @@ class BillingRepositoryImpl implements BillingRepository { @override Future getSavingsCents() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.billingSavings.path); + await _apiService.get(ClientEndpoints.billingSavings); final Map data = response.data as Map; return (data['savingsCents'] as num).toInt(); @@ -74,7 +74,7 @@ class BillingRepositoryImpl implements BillingRepository { required String endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.billingSpendBreakdown.path, + ClientEndpoints.billingSpendBreakdown, params: { 'startDate': startDate, 'endDate': endDate, @@ -90,13 +90,13 @@ class BillingRepositoryImpl implements BillingRepository { @override Future approveInvoice(String id) async { - await _apiService.post(ClientEndpoints.invoiceApprove(id).path); + await _apiService.post(ClientEndpoints.invoiceApprove(id)); } @override Future disputeInvoice(String id, String reason) async { await _apiService.post( - ClientEndpoints.invoiceDispute(id).path, + ClientEndpoints.invoiceDispute(id), data: {'reason': reason}, ); } diff --git a/apps/mobile/packages/features/client/client_coverage/lib/src/data/repositories_impl/coverage_repository_impl.dart b/apps/mobile/packages/features/client/client_coverage/lib/src/data/repositories_impl/coverage_repository_impl.dart index c331e9c4..2010cec5 100644 --- a/apps/mobile/packages/features/client/client_coverage/lib/src/data/repositories_impl/coverage_repository_impl.dart +++ b/apps/mobile/packages/features/client/client_coverage/lib/src/data/repositories_impl/coverage_repository_impl.dart @@ -20,7 +20,7 @@ class CoverageRepositoryImpl implements CoverageRepository { final String dateStr = '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; final ApiResponse response = await _apiService.get( - ClientEndpoints.coverage.path, + ClientEndpoints.coverage, params: {'date': dateStr}, ); final List items = response.data['items'] as List; @@ -35,7 +35,7 @@ class CoverageRepositoryImpl implements CoverageRepository { final String dateStr = '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; final ApiResponse response = await _apiService.get( - ClientEndpoints.coverageStats.path, + ClientEndpoints.coverageStats, params: {'date': dateStr}, ); return CoverageStats.fromJson(response.data as Map); @@ -67,7 +67,7 @@ class CoverageRepositoryImpl implements CoverageRepository { body['markAsFavorite'] = markAsFavorite; } await _apiService.post( - ClientEndpoints.coverageReviews.path, + ClientEndpoints.coverageReviews, data: body, ); } @@ -82,7 +82,7 @@ class CoverageRepositoryImpl implements CoverageRepository { body['reason'] = reason; } await _apiService.post( - ClientEndpoints.coverageCancelLateWorker(assignmentId).path, + ClientEndpoints.coverageCancelLateWorker(assignmentId), data: body, ); } diff --git a/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart b/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart index e6b9d1ed..ea756255 100644 --- a/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart +++ b/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart @@ -18,7 +18,7 @@ class HomeRepositoryImpl implements HomeRepositoryInterface { @override Future getDashboard() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.dashboard.path); + await _apiService.get(ClientEndpoints.dashboard); final Map data = response.data as Map; return ClientDashboard.fromJson(data); } @@ -26,7 +26,7 @@ class HomeRepositoryImpl implements HomeRepositoryInterface { @override Future> getRecentReorders() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.reorders.path); + await _apiService.get(ClientEndpoints.reorders); final Map body = response.data as Map; final List items = body['items'] as List; return items diff --git a/apps/mobile/packages/features/client/hubs/lib/src/data/repositories_impl/hub_repository_impl.dart b/apps/mobile/packages/features/client/hubs/lib/src/data/repositories_impl/hub_repository_impl.dart index ecd06f76..22b066d4 100644 --- a/apps/mobile/packages/features/client/hubs/lib/src/data/repositories_impl/hub_repository_impl.dart +++ b/apps/mobile/packages/features/client/hubs/lib/src/data/repositories_impl/hub_repository_impl.dart @@ -17,7 +17,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { @override Future> getHubs() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.hubs.path); + await _apiService.get(ClientEndpoints.hubs); final List items = (response.data as Map)['items'] as List; return items @@ -28,7 +28,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { @override Future> getCostCenters() async { final ApiResponse response = - await _apiService.get(ClientEndpoints.costCenters.path); + await _apiService.get(ClientEndpoints.costCenters); final List items = (response.data as Map)['items'] as List; return items @@ -52,7 +52,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { String? costCenterId, }) async { final ApiResponse response = await _apiService.post( - ClientEndpoints.hubCreate.path, + ClientEndpoints.hubCreate, data: { 'name': name, 'fullAddress': fullAddress, @@ -88,7 +88,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { String? costCenterId, }) async { final ApiResponse response = await _apiService.put( - ClientEndpoints.hubUpdate(hubId).path, + ClientEndpoints.hubUpdate(hubId), data: { 'hubId': hubId, if (name != null) 'name': name, @@ -111,7 +111,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { @override Future deleteHub(String hubId) async { - await _apiService.delete(ClientEndpoints.hubDelete(hubId).path); + await _apiService.delete(ClientEndpoints.hubDelete(hubId)); } @override @@ -120,7 +120,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { required String nfcTagId, }) async { await _apiService.post( - ClientEndpoints.hubAssignNfc(hubId).path, + ClientEndpoints.hubAssignNfc(hubId), data: {'nfcTagId': nfcTagId}, ); } @@ -128,7 +128,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { @override Future> getManagers(String hubId) async { final ApiResponse response = - await _apiService.get(ClientEndpoints.hubManagers(hubId).path); + await _apiService.get(ClientEndpoints.hubManagers(hubId)); final List items = (response.data as Map)['items'] as List; return items @@ -143,7 +143,7 @@ class HubRepositoryImpl implements HubRepositoryInterface { required List businessMembershipIds, }) async { await _apiService.post( - ClientEndpoints.hubAssignManagers(hubId).path, + ClientEndpoints.hubAssignManagers(hubId), data: { 'businessMembershipIds': businessMembershipIds, }, diff --git a/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_create_order_repository_impl.dart b/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_create_order_repository_impl.dart index 6efc9179..7739e41e 100644 --- a/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_create_order_repository_impl.dart +++ b/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_create_order_repository_impl.dart @@ -24,17 +24,17 @@ class ClientCreateOrderRepositoryImpl @override Future createOneTimeOrder(Map payload) async { - await _api.post(ClientEndpoints.ordersOneTime.path, data: payload); + await _api.post(ClientEndpoints.ordersOneTime, data: payload); } @override Future createRecurringOrder(Map payload) async { - await _api.post(ClientEndpoints.ordersRecurring.path, data: payload); + await _api.post(ClientEndpoints.ordersRecurring, data: payload); } @override Future createPermanentOrder(Map payload) async { - await _api.post(ClientEndpoints.ordersPermanent.path, data: payload); + await _api.post(ClientEndpoints.ordersPermanent, data: payload); } @override @@ -82,7 +82,7 @@ class ClientCreateOrderRepositoryImpl @override Future getOrderDetailsForReorder(String orderId) async { final ApiResponse response = await _api.get( - ClientEndpoints.orderReorderPreview(orderId).path, + ClientEndpoints.orderReorderPreview(orderId), ); return OrderPreview.fromJson(response.data as Map); } diff --git a/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_order_query_repository_impl.dart b/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_order_query_repository_impl.dart index b1d62cb8..967da1b6 100644 --- a/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_order_query_repository_impl.dart +++ b/apps/mobile/packages/features/client/orders/create_order/lib/src/data/repositories_impl/client_order_query_repository_impl.dart @@ -19,7 +19,7 @@ class ClientOrderQueryRepositoryImpl @override Future> getVendors() async { - final ApiResponse response = await _api.get(ClientEndpoints.vendors.path); + final ApiResponse response = await _api.get(ClientEndpoints.vendors); final Map data = response.data as Map; final List items = data['items'] as List; return items @@ -30,7 +30,7 @@ class ClientOrderQueryRepositoryImpl @override Future> getRolesByVendor(String vendorId) async { final ApiResponse response = - await _api.get(ClientEndpoints.vendorRoles(vendorId).path); + await _api.get(ClientEndpoints.vendorRoles(vendorId)); final Map data = response.data as Map; final List items = data['items'] as List; return items.map((dynamic json) { @@ -46,7 +46,7 @@ class ClientOrderQueryRepositoryImpl @override Future> getHubs() async { - final ApiResponse response = await _api.get(ClientEndpoints.hubs.path); + final ApiResponse response = await _api.get(ClientEndpoints.hubs); final Map data = response.data as Map; final List items = data['items'] as List; return items.map((dynamic json) { @@ -71,7 +71,7 @@ class ClientOrderQueryRepositoryImpl @override Future> getManagersByHub(String hubId) async { final ApiResponse response = - await _api.get(ClientEndpoints.hubManagers(hubId).path); + await _api.get(ClientEndpoints.hubManagers(hubId)); final Map data = response.data as Map; final List items = data['items'] as List; return items.map((dynamic json) { diff --git a/apps/mobile/packages/features/client/orders/view_orders/lib/src/data/repositories/view_orders_repository_impl.dart b/apps/mobile/packages/features/client/orders/view_orders/lib/src/data/repositories/view_orders_repository_impl.dart index a12fce25..2f656e39 100644 --- a/apps/mobile/packages/features/client/orders/view_orders/lib/src/data/repositories/view_orders_repository_impl.dart +++ b/apps/mobile/packages/features/client/orders/view_orders/lib/src/data/repositories/view_orders_repository_impl.dart @@ -20,7 +20,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { required DateTime end, }) async { final ApiResponse response = await _api.get( - ClientEndpoints.ordersView.path, + ClientEndpoints.ordersView, params: { 'startDate': start.toIso8601String(), 'endDate': end.toIso8601String(), @@ -40,7 +40,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { required Map payload, }) async { final ApiResponse response = await _api.post( - ClientEndpoints.orderEdit(orderId).path, + ClientEndpoints.orderEdit(orderId), data: payload, ); final Map data = response.data as Map; @@ -53,7 +53,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { String? reason, }) async { await _api.post( - ClientEndpoints.orderCancel(orderId).path, + ClientEndpoints.orderCancel(orderId), data: { if (reason != null) 'reason': reason, }, @@ -62,7 +62,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { @override Future> getVendors() async { - final ApiResponse response = await _api.get(ClientEndpoints.vendors.path); + final ApiResponse response = await _api.get(ClientEndpoints.vendors); final Map data = response.data as Map; final List items = data['items'] as List; return items @@ -73,7 +73,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { @override Future>> getRolesByVendor(String vendorId) async { final ApiResponse response = - await _api.get(ClientEndpoints.vendorRoles(vendorId).path); + await _api.get(ClientEndpoints.vendorRoles(vendorId)); final Map data = response.data as Map; final List items = data['items'] as List; return items.cast>(); @@ -81,7 +81,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { @override Future>> getHubs() async { - final ApiResponse response = await _api.get(ClientEndpoints.hubs.path); + final ApiResponse response = await _api.get(ClientEndpoints.hubs); final Map data = response.data as Map; final List items = data['items'] as List; return items.cast>(); @@ -90,7 +90,7 @@ class ViewOrdersRepositoryImpl implements IViewOrdersRepository { @override Future>> getManagersByHub(String hubId) async { final ApiResponse response = - await _api.get(ClientEndpoints.hubManagers(hubId).path); + await _api.get(ClientEndpoints.hubManagers(hubId)); final Map data = response.data as Map; final List items = data['items'] as List; return items.cast>(); diff --git a/apps/mobile/packages/features/client/reports/lib/src/data/repositories_impl/reports_repository_impl.dart b/apps/mobile/packages/features/client/reports/lib/src/data/repositories_impl/reports_repository_impl.dart index f067d464..40853550 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/data/repositories_impl/reports_repository_impl.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/data/repositories_impl/reports_repository_impl.dart @@ -32,7 +32,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime date, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsDailyOps.path, + ClientEndpoints.reportsDailyOps, params: {'date': _iso(date)}, ); final Map data = response.data as Map; @@ -45,7 +45,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsSpend.path, + ClientEndpoints.reportsSpend, params: _rangeParams(startDate, endDate), ); final Map data = response.data as Map; @@ -58,7 +58,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsCoverage.path, + ClientEndpoints.reportsCoverage, params: _rangeParams(startDate, endDate), ); final Map data = response.data as Map; @@ -71,7 +71,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsForecast.path, + ClientEndpoints.reportsForecast, params: _rangeParams(startDate, endDate), ); final Map data = response.data as Map; @@ -84,7 +84,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsPerformance.path, + ClientEndpoints.reportsPerformance, params: _rangeParams(startDate, endDate), ); final Map data = response.data as Map; @@ -97,7 +97,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsNoShow.path, + ClientEndpoints.reportsNoShow, params: _rangeParams(startDate, endDate), ); final Map data = response.data as Map; @@ -110,7 +110,7 @@ class ReportsRepositoryImpl implements ReportsRepository { required DateTime endDate, }) async { final ApiResponse response = await _apiService.get( - ClientEndpoints.reportsSummary.path, + ClientEndpoints.reportsSummary, params: _rangeParams(startDate, endDate), ); final Map data = response.data as Map; diff --git a/apps/mobile/packages/features/client/settings/lib/src/data/repositories_impl/settings_repository_impl.dart b/apps/mobile/packages/features/client/settings/lib/src/data/repositories_impl/settings_repository_impl.dart index ce114987..15ff9337 100644 --- a/apps/mobile/packages/features/client/settings/lib/src/data/repositories_impl/settings_repository_impl.dart +++ b/apps/mobile/packages/features/client/settings/lib/src/data/repositories_impl/settings_repository_impl.dart @@ -22,7 +22,7 @@ class SettingsRepositoryImpl implements SettingsRepositoryInterface { Future signOut() async { try { // Step 1: Call V2 sign-out endpoint for server-side token revocation. - await _apiService.post(AuthEndpoints.clientSignOut.path); + await _apiService.post(AuthEndpoints.clientSignOut); } catch (e) { developer.log( 'V2 sign-out request failed: $e', diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart b/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart index 6db9cd94..b3c92f14 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart @@ -63,7 +63,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface { try { final domain.ApiResponse startResponse = await _apiService.post( - AuthEndpoints.staffPhoneStart.path, + AuthEndpoints.staffPhoneStart, data: { 'phoneNumber': phoneNumber, }, @@ -182,7 +182,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface { // Step 3: Call V2 verify endpoint with the Firebase ID token. final String v2Mode = mode == AuthMode.signup ? 'sign-up' : 'sign-in'; final domain.ApiResponse response = await _apiService.post( - AuthEndpoints.staffPhoneVerify.path, + AuthEndpoints.staffPhoneVerify, data: { 'idToken': idToken, 'mode': v2Mode, @@ -233,7 +233,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface { @override Future signOut() async { try { - await _apiService.post(AuthEndpoints.staffSignOut.path); + await _apiService.post(AuthEndpoints.staffSignOut); } catch (_) { // Sign-out should not fail even if the API call fails. // The local sign-out below will clear the session regardless. diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/profile_setup_repository_impl.dart b/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/profile_setup_repository_impl.dart index ecb52730..2ca01e07 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/profile_setup_repository_impl.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/profile_setup_repository_impl.dart @@ -27,7 +27,7 @@ class ProfileSetupRepositoryImpl implements ProfileSetupRepository { required List skills, }) async { final ApiResponse response = await _apiService.post( - StaffEndpoints.profileSetup.path, + StaffEndpoints.profileSetup, data: { 'fullName': fullName, if (bio != null && bio.isNotEmpty) 'bio': bio, diff --git a/apps/mobile/packages/features/staff/availability/lib/src/data/repositories_impl/availability_repository_impl.dart b/apps/mobile/packages/features/staff/availability/lib/src/data/repositories_impl/availability_repository_impl.dart index fc0b6669..a402b6ee 100644 --- a/apps/mobile/packages/features/staff/availability/lib/src/data/repositories_impl/availability_repository_impl.dart +++ b/apps/mobile/packages/features/staff/availability/lib/src/data/repositories_impl/availability_repository_impl.dart @@ -25,7 +25,7 @@ class AvailabilityRepositoryImpl implements AvailabilityRepository { final String endDate = _toIsoDate(end); final ApiResponse response = await _apiService.get( - StaffEndpoints.availability.path, + StaffEndpoints.availability, params: { 'startDate': startDate, 'endDate': endDate, @@ -48,7 +48,7 @@ class AvailabilityRepositoryImpl implements AvailabilityRepository { required List slots, }) async { final ApiResponse response = await _apiService.put( - StaffEndpoints.availability.path, + StaffEndpoints.availability, data: { 'dayOfWeek': dayOfWeek, 'availabilityStatus': status.toJson(), @@ -86,7 +86,7 @@ class AvailabilityRepositoryImpl implements AvailabilityRepository { } await _apiService.post( - StaffEndpoints.availabilityQuickSet.path, + StaffEndpoints.availabilityQuickSet, data: data, ); } diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/data/repositories_impl/clock_in_repository_impl.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/data/repositories_impl/clock_in_repository_impl.dart index efc2599b..ee44c6a2 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/data/repositories_impl/clock_in_repository_impl.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/data/repositories_impl/clock_in_repository_impl.dart @@ -17,7 +17,7 @@ class ClockInRepositoryImpl implements ClockInRepositoryInterface { @override Future> getTodaysShifts() async { final ApiResponse response = await _apiService.get( - StaffEndpoints.clockInShiftsToday.path, + StaffEndpoints.clockInShiftsToday, ); final List items = response.data['items'] as List; // TODO: Ask BE to add latitude, longitude, hourlyRate, and clientName @@ -33,7 +33,7 @@ class ClockInRepositoryImpl implements ClockInRepositoryInterface { @override Future getAttendanceStatus() async { final ApiResponse response = await _apiService.get( - StaffEndpoints.clockInStatus.path, + StaffEndpoints.clockInStatus, ); return AttendanceStatus.fromJson(response.data as Map); } @@ -44,7 +44,7 @@ class ClockInRepositoryImpl implements ClockInRepositoryInterface { String? notes, }) async { await _apiService.post( - StaffEndpoints.clockIn.path, + StaffEndpoints.clockIn, data: { 'shiftId': shiftId, 'sourceType': 'GEO', @@ -62,7 +62,7 @@ class ClockInRepositoryImpl implements ClockInRepositoryInterface { String? shiftId, }) async { await _apiService.post( - StaffEndpoints.clockOut.path, + StaffEndpoints.clockOut, data: { if (shiftId != null) 'shiftId': shiftId, 'sourceType': 'GEO', diff --git a/apps/mobile/packages/features/staff/home/lib/src/data/repositories/home_repository_impl.dart b/apps/mobile/packages/features/staff/home/lib/src/data/repositories/home_repository_impl.dart index 9da08cc3..bc69b23c 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/data/repositories/home_repository_impl.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/data/repositories/home_repository_impl.dart @@ -17,7 +17,7 @@ class HomeRepositoryImpl implements HomeRepository { @override Future getDashboard() async { final ApiResponse response = - await _apiService.get(StaffEndpoints.dashboard.path); + await _apiService.get(StaffEndpoints.dashboard); final Map data = response.data as Map; return StaffDashboard.fromJson(data); } @@ -25,7 +25,7 @@ class HomeRepositoryImpl implements HomeRepository { @override Future getProfileCompletion() async { final ApiResponse response = - await _apiService.get(StaffEndpoints.profileCompletion.path); + await _apiService.get(StaffEndpoints.profileCompletion); final Map data = response.data as Map; final ProfileCompletion completion = ProfileCompletion.fromJson(data); return completion.completed; diff --git a/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart b/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart index c20155e7..aa0ea027 100644 --- a/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart +++ b/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart @@ -24,7 +24,7 @@ class PaymentsRepositoryImpl implements PaymentsRepository { if (endDate != null) 'endDate': endDate, }; final ApiResponse response = await _apiService.get( - StaffEndpoints.paymentsSummary.path, + StaffEndpoints.paymentsSummary, params: params.isEmpty ? null : params, ); return PaymentSummary.fromJson(response.data as Map); @@ -40,7 +40,7 @@ class PaymentsRepositoryImpl implements PaymentsRepository { if (endDate != null) 'endDate': endDate, }; final ApiResponse response = await _apiService.get( - StaffEndpoints.paymentsHistory.path, + StaffEndpoints.paymentsHistory, params: params.isEmpty ? null : params, ); final Map body = response.data as Map; @@ -63,7 +63,7 @@ class PaymentsRepositoryImpl implements PaymentsRepository { if (endDate != null) 'endDate': endDate, }; final ApiResponse response = await _apiService.get( - StaffEndpoints.paymentsChart.path, + StaffEndpoints.paymentsChart, params: params, ); final Map body = response.data as Map; diff --git a/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart b/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart index 49b8012f..606d08f0 100644 --- a/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart @@ -14,7 +14,7 @@ class ProfileRepositoryImpl { /// Fetches the staff profile from the V2 session endpoint. Future getStaffProfile() async { final ApiResponse response = - await _api.get(StaffEndpoints.session.path); + await _api.get(StaffEndpoints.session); final Map json = response.data['staff'] as Map; return Staff.fromJson(json); @@ -23,7 +23,7 @@ class ProfileRepositoryImpl { /// Fetches the profile section completion statuses. Future getProfileSections() async { final ApiResponse response = - await _api.get(StaffEndpoints.profileSections.path); + await _api.get(StaffEndpoints.profileSections); final Map json = response.data as Map; return ProfileSectionStatus.fromJson(json); @@ -31,6 +31,6 @@ class ProfileRepositoryImpl { /// Signs out the current user. Future signOut() async { - await _api.post(AuthEndpoints.signOut.path); + await _api.post(AuthEndpoints.signOut); } } diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/certificates/lib/src/data/repositories_impl/certificates_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/certificates/lib/src/data/repositories_impl/certificates_repository_impl.dart index 22ab7e00..b1762a77 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/certificates/lib/src/data/repositories_impl/certificates_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/certificates/lib/src/data/repositories_impl/certificates_repository_impl.dart @@ -27,7 +27,7 @@ class CertificatesRepositoryImpl implements CertificatesRepository { @override Future> getCertificates() async { final ApiResponse response = - await _api.get(StaffEndpoints.certificates.path); + await _api.get(StaffEndpoints.certificates); final List items = response.data['certificates'] as List; return items @@ -73,7 +73,7 @@ class CertificatesRepositoryImpl implements CertificatesRepository { // 4. Save certificate via V2 API await _api.post( - StaffEndpoints.certificates.path, + StaffEndpoints.certificates, data: { 'certificateType': certificateType, 'name': name, @@ -95,7 +95,7 @@ class CertificatesRepositoryImpl implements CertificatesRepository { @override Future deleteCertificate({required String certificateId}) async { await _api.delete( - StaffEndpoints.certificateDelete(certificateId).path, + StaffEndpoints.certificateDelete(certificateId), ); } } diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/documents/lib/src/data/repositories_impl/documents_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/documents/lib/src/data/repositories_impl/documents_repository_impl.dart index 76c7023b..01505378 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/documents/lib/src/data/repositories_impl/documents_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/documents/lib/src/data/repositories_impl/documents_repository_impl.dart @@ -27,7 +27,7 @@ class DocumentsRepositoryImpl implements DocumentsRepository { @override Future> getDocuments() async { final ApiResponse response = - await _api.get(StaffEndpoints.documents.path); + await _api.get(StaffEndpoints.documents); final List items = response.data['documents'] as List; return items .map((dynamic json) => @@ -64,7 +64,7 @@ class DocumentsRepositoryImpl implements DocumentsRepository { // 4. Submit upload result to V2 API await _api.put( - StaffEndpoints.documentUpload(documentId).path, + StaffEndpoints.documentUpload(documentId), data: { 'fileUri': signedUrlRes.signedUrl, 'verificationId': verificationRes.verificationId, diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart index 5961f3d8..d3d36e39 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart @@ -18,7 +18,7 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository { @override Future> getTaxForms() async { final ApiResponse response = - await _api.get(StaffEndpoints.taxForms.path); + await _api.get(StaffEndpoints.taxForms); final List items = response.data['taxForms'] as List; return items .map((dynamic json) => @@ -29,7 +29,7 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository { @override Future updateTaxForm(TaxForm form) async { await _api.put( - StaffEndpoints.taxFormUpdate(form.formType).path, + StaffEndpoints.taxFormUpdate(form.formType), data: form.toJson(), ); } @@ -37,7 +37,7 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository { @override Future submitTaxForm(TaxForm form) async { await _api.post( - StaffEndpoints.taxFormSubmit(form.formType).path, + StaffEndpoints.taxFormSubmit(form.formType), data: form.toJson(), ); } diff --git a/apps/mobile/packages/features/staff/profile_sections/finances/staff_bank_account/lib/src/data/repositories/bank_account_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/finances/staff_bank_account/lib/src/data/repositories/bank_account_repository_impl.dart index 46ac8b8f..48058367 100644 --- a/apps/mobile/packages/features/staff/profile_sections/finances/staff_bank_account/lib/src/data/repositories/bank_account_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/finances/staff_bank_account/lib/src/data/repositories/bank_account_repository_impl.dart @@ -16,7 +16,7 @@ class BankAccountRepositoryImpl implements BankAccountRepository { @override Future> getAccounts() async { final ApiResponse response = - await _api.get(StaffEndpoints.bankAccounts.path); + await _api.get(StaffEndpoints.bankAccounts); final List items = response.data['accounts'] as List; return items .map((dynamic json) => @@ -27,7 +27,7 @@ class BankAccountRepositoryImpl implements BankAccountRepository { @override Future addAccount(BankAccount account) async { await _api.post( - StaffEndpoints.bankAccounts.path, + StaffEndpoints.bankAccounts, data: account.toJson(), ); } diff --git a/apps/mobile/packages/features/staff/profile_sections/finances/time_card/lib/src/data/repositories_impl/time_card_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/finances/time_card/lib/src/data/repositories_impl/time_card_repository_impl.dart index 82261445..f72d0803 100644 --- a/apps/mobile/packages/features/staff/profile_sections/finances/time_card/lib/src/data/repositories_impl/time_card_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/finances/time_card/lib/src/data/repositories_impl/time_card_repository_impl.dart @@ -16,7 +16,7 @@ class TimeCardRepositoryImpl implements TimeCardRepository { @override Future> getTimeCards(DateTime month) async { final ApiResponse response = await _api.get( - StaffEndpoints.timeCard.path, + StaffEndpoints.timeCard, params: { 'year': month.year, 'month': month.month, diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart index ba00457c..5c9b9369 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart @@ -27,7 +27,7 @@ class AttireRepositoryImpl implements AttireRepository { @override Future> getAttireOptions() async { - final ApiResponse response = await _api.get(StaffEndpoints.attire.path); + final ApiResponse response = await _api.get(StaffEndpoints.attire); final List items = response.data['items'] as List; return items .map((dynamic json) => @@ -100,7 +100,7 @@ class AttireRepositoryImpl implements AttireRepository { // 5. Update attire item via V2 API await _api.put( - StaffEndpoints.attireUpload(itemId).path, + StaffEndpoints.attireUpload(itemId), data: { 'photoUrl': photoUrl, 'verificationId': verifyRes.verificationId, diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart index ba8f01a0..52be33d2 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart @@ -17,7 +17,7 @@ class EmergencyContactRepositoryImpl @override Future> getContacts() async { final ApiResponse response = - await _api.get(StaffEndpoints.emergencyContacts.path); + await _api.get(StaffEndpoints.emergencyContacts); final List items = response.data['contacts'] as List; return items .map((dynamic json) => @@ -28,7 +28,7 @@ class EmergencyContactRepositoryImpl @override Future saveContacts(List contacts) async { await _api.put( - StaffEndpoints.emergencyContacts.path, + StaffEndpoints.emergencyContacts, data: { 'contacts': contacts.map((EmergencyContact c) => c.toJson()).toList(), diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart index 5e25f550..28ae1150 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart @@ -16,14 +16,14 @@ class ExperienceRepositoryImpl implements ExperienceRepositoryInterface { @override Future> getIndustries() async { final ApiResponse response = - await _api.get(StaffEndpoints.industries.path); + await _api.get(StaffEndpoints.industries); final List items = response.data['industries'] as List; return items.map((dynamic e) => e.toString()).toList(); } @override Future> getSkills() async { - final ApiResponse response = await _api.get(StaffEndpoints.skills.path); + final ApiResponse response = await _api.get(StaffEndpoints.skills); final List items = response.data['skills'] as List; return items.map((dynamic e) => e.toString()).toList(); } @@ -34,7 +34,7 @@ class ExperienceRepositoryImpl implements ExperienceRepositoryInterface { List skills, ) async { await _api.put( - StaffEndpoints.personalInfo.path, + StaffEndpoints.personalInfo, data: { 'industries': industries, 'skills': skills, diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart index ade14cba..75fc0a01 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart @@ -28,7 +28,7 @@ class PersonalInfoRepositoryImpl implements PersonalInfoRepositoryInterface { @override Future getStaffProfile() async { final ApiResponse response = - await _api.get(StaffEndpoints.personalInfo.path); + await _api.get(StaffEndpoints.personalInfo); final Map json = response.data as Map; return StaffPersonalInfo.fromJson(json); @@ -40,7 +40,7 @@ class PersonalInfoRepositoryImpl implements PersonalInfoRepositoryInterface { required Map data, }) async { final ApiResponse response = await _api.put( - StaffEndpoints.personalInfo.path, + StaffEndpoints.personalInfo, data: data, ); final Map json = @@ -65,7 +65,7 @@ class PersonalInfoRepositoryImpl implements PersonalInfoRepositoryInterface { // 3. Submit the photo URL to the V2 API. await _api.post( - StaffEndpoints.profilePhoto.path, + StaffEndpoints.profilePhoto, data: { 'fileUri': uploadRes.fileUri, 'photoUrl': photoUrl, diff --git a/apps/mobile/packages/features/staff/profile_sections/support/faqs/lib/src/data/repositories_impl/faqs_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/support/faqs/lib/src/data/repositories_impl/faqs_repository_impl.dart index c8f26470..7e6fea1a 100644 --- a/apps/mobile/packages/features/staff/profile_sections/support/faqs/lib/src/data/repositories_impl/faqs_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/support/faqs/lib/src/data/repositories_impl/faqs_repository_impl.dart @@ -18,7 +18,7 @@ class FaqsRepositoryImpl implements FaqsRepositoryInterface { Future> getFaqs() async { try { final ApiResponse response = - await _apiService.get(StaffEndpoints.faqs.path); + await _apiService.get(StaffEndpoints.faqs); return _parseCategories(response); } catch (_) { return []; @@ -29,7 +29,7 @@ class FaqsRepositoryImpl implements FaqsRepositoryInterface { Future> searchFaqs(String query) async { try { final ApiResponse response = await _apiService.get( - StaffEndpoints.faqsSearch.path, + StaffEndpoints.faqsSearch, params: {'q': query}, ); return _parseCategories(response); diff --git a/apps/mobile/packages/features/staff/profile_sections/support/privacy_security/lib/src/data/repositories_impl/privacy_settings_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/support/privacy_security/lib/src/data/repositories_impl/privacy_settings_repository_impl.dart index 24b49a99..fe50221b 100644 --- a/apps/mobile/packages/features/staff/profile_sections/support/privacy_security/lib/src/data/repositories_impl/privacy_settings_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/support/privacy_security/lib/src/data/repositories_impl/privacy_settings_repository_impl.dart @@ -19,7 +19,7 @@ class PrivacySettingsRepositoryImpl @override Future getProfileVisibility() async { final ApiResponse response = - await _api.get(StaffEndpoints.privacy.path); + await _api.get(StaffEndpoints.privacy); final Map json = response.data as Map; final PrivacySettings settings = PrivacySettings.fromJson(json); @@ -29,7 +29,7 @@ class PrivacySettingsRepositoryImpl @override Future updateProfileVisibility(bool isVisible) async { await _api.put( - StaffEndpoints.privacy.path, + StaffEndpoints.privacy, data: {'profileVisible': isVisible}, ); return isVisible; diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/data/repositories_impl/shifts_repository_impl.dart b/apps/mobile/packages/features/staff/shifts/lib/src/data/repositories_impl/shifts_repository_impl.dart index 4057a0af..8835d825 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/data/repositories_impl/shifts_repository_impl.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/data/repositories_impl/shifts_repository_impl.dart @@ -34,7 +34,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { required DateTime end, }) async { final ApiResponse response = await _apiService.get( - StaffEndpoints.shiftsAssigned.path, + StaffEndpoints.shiftsAssigned, params: { 'startDate': start.toIso8601String(), 'endDate': end.toIso8601String(), @@ -59,7 +59,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { params['search'] = search; } final ApiResponse response = await _apiService.get( - StaffEndpoints.shiftsOpen.path, + StaffEndpoints.shiftsOpen, params: params, ); final List items = _extractItems(response.data); @@ -72,7 +72,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { @override Future> getPendingAssignments() async { final ApiResponse response = - await _apiService.get(StaffEndpoints.shiftsPending.path); + await _apiService.get(StaffEndpoints.shiftsPending); final List items = _extractItems(response.data); return items .map((dynamic json) => @@ -83,7 +83,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { @override Future> getCancelledShifts() async { final ApiResponse response = - await _apiService.get(StaffEndpoints.shiftsCancelled.path); + await _apiService.get(StaffEndpoints.shiftsCancelled); final List items = _extractItems(response.data); return items .map((dynamic json) => @@ -94,7 +94,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { @override Future> getCompletedShifts() async { final ApiResponse response = - await _apiService.get(StaffEndpoints.shiftsCompleted.path); + await _apiService.get(StaffEndpoints.shiftsCompleted); final List items = _extractItems(response.data); return items .map((dynamic json) => @@ -105,7 +105,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { @override Future getShiftDetail(String shiftId) async { final ApiResponse response = - await _apiService.get(StaffEndpoints.shiftDetails(shiftId).path); + await _apiService.get(StaffEndpoints.shiftDetails(shiftId)); if (response.data == null) { return null; } @@ -119,7 +119,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { bool instantBook = false, }) async { await _apiService.post( - StaffEndpoints.shiftApply(shiftId).path, + StaffEndpoints.shiftApply(shiftId), data: { if (roleId != null) 'roleId': roleId, 'instantBook': instantBook, @@ -129,18 +129,18 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { @override Future acceptShift(String shiftId) async { - await _apiService.post(StaffEndpoints.shiftAccept(shiftId).path); + await _apiService.post(StaffEndpoints.shiftAccept(shiftId)); } @override Future declineShift(String shiftId) async { - await _apiService.post(StaffEndpoints.shiftDecline(shiftId).path); + await _apiService.post(StaffEndpoints.shiftDecline(shiftId)); } @override Future requestSwap(String shiftId, {String? reason}) async { await _apiService.post( - StaffEndpoints.shiftRequestSwap(shiftId).path, + StaffEndpoints.shiftRequestSwap(shiftId), data: { if (reason != null) 'reason': reason, }, @@ -150,7 +150,7 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface { @override Future getProfileCompletion() async { final ApiResponse response = - await _apiService.get(StaffEndpoints.profileCompletion.path); + await _apiService.get(StaffEndpoints.profileCompletion); final Map data = response.data as Map; final ProfileCompletion completion = ProfileCompletion.fromJson(data); return completion.completed; diff --git a/apps/mobile/packages/features/staff/staff_main/lib/src/data/repositories/staff_main_repository_impl.dart b/apps/mobile/packages/features/staff/staff_main/lib/src/data/repositories/staff_main_repository_impl.dart index 24232d75..01f76599 100644 --- a/apps/mobile/packages/features/staff/staff_main/lib/src/data/repositories/staff_main_repository_impl.dart +++ b/apps/mobile/packages/features/staff/staff_main/lib/src/data/repositories/staff_main_repository_impl.dart @@ -23,7 +23,7 @@ class StaffMainRepositoryImpl implements StaffMainRepositoryInterface { Future getProfileCompletion() async { try { final ApiResponse response = await _apiService.get( - StaffEndpoints.profileCompletion.path, + StaffEndpoints.profileCompletion, ); if (response.data is Map) {