feat(shifts): implement submit for approval functionality
- Added `submitForApproval` method to `ShiftsRepositoryInterface` and its implementation in `ShiftsRepositoryImpl`. - Created `SubmitForApprovalUseCase` to handle the submission logic. - Updated `ShiftsBloc` to handle `SubmitForApprovalEvent` and manage submission state. - Enhanced `HistoryShiftsTab` and `MyShiftsTab` to support submission actions and display appropriate UI feedback. - Refactored date utilities for better calendar management and filtering of past shifts. - Improved UI components for better spacing and alignment. - Localized success messages for shift submission actions.
This commit is contained in:
@@ -42,6 +42,9 @@ export 'src/services/session/client_session_store.dart';
|
||||
export 'src/services/session/staff_session_store.dart';
|
||||
export 'src/services/session/v2_session_service.dart';
|
||||
|
||||
// Auth
|
||||
export 'src/services/auth/auth_token_provider.dart';
|
||||
|
||||
// Device Services
|
||||
export 'src/services/device/camera/camera_service.dart';
|
||||
export 'src/services/device/gallery/gallery_service.dart';
|
||||
|
||||
@@ -3,6 +3,9 @@ import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
import 'package:krow_core/src/services/auth/auth_token_provider.dart';
|
||||
import 'package:krow_core/src/services/auth/firebase_auth_token_provider.dart';
|
||||
|
||||
import '../core.dart';
|
||||
|
||||
/// A module that provides core services and shared dependencies.
|
||||
@@ -57,7 +60,10 @@ class CoreModule extends Module {
|
||||
),
|
||||
);
|
||||
|
||||
// 6. Register Geofence Device Services
|
||||
// 6. Auth Token Provider
|
||||
i.addLazySingleton<AuthTokenProvider>(FirebaseAuthTokenProvider.new);
|
||||
|
||||
// 7. Register Geofence Device Services
|
||||
i.addLazySingleton<LocationService>(() => const LocationService());
|
||||
i.addLazySingleton<NotificationService>(() => NotificationService());
|
||||
i.addLazySingleton<StorageService>(() => StorageService());
|
||||
|
||||
@@ -48,6 +48,26 @@ abstract final class ClientEndpoints {
|
||||
static const ApiEndpoint coverageCoreTeam =
|
||||
ApiEndpoint('/client/coverage/core-team');
|
||||
|
||||
/// Coverage incidents.
|
||||
static const ApiEndpoint coverageIncidents =
|
||||
ApiEndpoint('/client/coverage/incidents');
|
||||
|
||||
/// Blocked staff.
|
||||
static const ApiEndpoint coverageBlockedStaff =
|
||||
ApiEndpoint('/client/coverage/blocked-staff');
|
||||
|
||||
/// Coverage swap requests.
|
||||
static const ApiEndpoint coverageSwapRequests =
|
||||
ApiEndpoint('/client/coverage/swap-requests');
|
||||
|
||||
/// Dispatch teams.
|
||||
static const ApiEndpoint coverageDispatchTeams =
|
||||
ApiEndpoint('/client/coverage/dispatch-teams');
|
||||
|
||||
/// Dispatch candidates.
|
||||
static const ApiEndpoint coverageDispatchCandidates =
|
||||
ApiEndpoint('/client/coverage/dispatch-candidates');
|
||||
|
||||
/// Hubs list.
|
||||
static const ApiEndpoint hubs = ApiEndpoint('/client/hubs');
|
||||
|
||||
@@ -162,4 +182,28 @@ abstract final class ClientEndpoints {
|
||||
/// Cancel late worker assignment.
|
||||
static ApiEndpoint coverageCancelLateWorker(String assignmentId) =>
|
||||
ApiEndpoint('/client/coverage/late-workers/$assignmentId/cancel');
|
||||
|
||||
/// Register or delete device push token (POST to register, DELETE to remove).
|
||||
static const ApiEndpoint devicesPushTokens =
|
||||
ApiEndpoint('/client/devices/push-tokens');
|
||||
|
||||
/// Create shift manager.
|
||||
static const ApiEndpoint shiftManagerCreate =
|
||||
ApiEndpoint('/client/shift-managers');
|
||||
|
||||
/// Resolve coverage swap request by ID.
|
||||
static ApiEndpoint coverageSwapRequestResolve(String id) =>
|
||||
ApiEndpoint('/client/coverage/swap-requests/$id/resolve');
|
||||
|
||||
/// Cancel coverage swap request by ID.
|
||||
static ApiEndpoint coverageSwapRequestCancel(String id) =>
|
||||
ApiEndpoint('/client/coverage/swap-requests/$id/cancel');
|
||||
|
||||
/// Create dispatch team membership.
|
||||
static const ApiEndpoint coverageDispatchTeamMembershipsCreate =
|
||||
ApiEndpoint('/client/coverage/dispatch-teams/memberships');
|
||||
|
||||
/// Delete dispatch team membership by ID.
|
||||
static ApiEndpoint coverageDispatchTeamMembershipsDelete(String id) =>
|
||||
ApiEndpoint('/client/coverage/dispatch-teams/memberships/$id');
|
||||
}
|
||||
|
||||
@@ -2,39 +2,42 @@ import 'package:krow_domain/krow_domain.dart' show ApiEndpoint;
|
||||
|
||||
/// Core infrastructure endpoints (upload, signed URLs, LLM, verifications,
|
||||
/// rapid orders).
|
||||
///
|
||||
/// Paths are at the unified API root level (not under `/core/`).
|
||||
abstract final class CoreEndpoints {
|
||||
/// Upload a file.
|
||||
static const ApiEndpoint uploadFile =
|
||||
ApiEndpoint('/core/upload-file');
|
||||
static const ApiEndpoint uploadFile = ApiEndpoint('/upload-file');
|
||||
|
||||
/// Create a signed URL for a file.
|
||||
static const ApiEndpoint createSignedUrl =
|
||||
ApiEndpoint('/core/create-signed-url');
|
||||
static const ApiEndpoint createSignedUrl = ApiEndpoint('/create-signed-url');
|
||||
|
||||
/// Invoke a Large Language Model.
|
||||
static const ApiEndpoint invokeLlm = ApiEndpoint('/core/invoke-llm');
|
||||
static const ApiEndpoint invokeLlm = ApiEndpoint('/invoke-llm');
|
||||
|
||||
/// Root for verification operations.
|
||||
static const ApiEndpoint verifications =
|
||||
ApiEndpoint('/core/verifications');
|
||||
static const ApiEndpoint verifications = ApiEndpoint('/verifications');
|
||||
|
||||
/// Get status of a verification job.
|
||||
static ApiEndpoint verificationStatus(String id) =>
|
||||
ApiEndpoint('/core/verifications/$id');
|
||||
ApiEndpoint('/verifications/$id');
|
||||
|
||||
/// Review a verification decision.
|
||||
static ApiEndpoint verificationReview(String id) =>
|
||||
ApiEndpoint('/core/verifications/$id/review');
|
||||
ApiEndpoint('/verifications/$id/review');
|
||||
|
||||
/// Retry a verification job.
|
||||
static ApiEndpoint verificationRetry(String id) =>
|
||||
ApiEndpoint('/core/verifications/$id/retry');
|
||||
ApiEndpoint('/verifications/$id/retry');
|
||||
|
||||
/// Transcribe audio to text for rapid orders.
|
||||
static const ApiEndpoint transcribeRapidOrder =
|
||||
ApiEndpoint('/core/rapid-orders/transcribe');
|
||||
ApiEndpoint('/rapid-orders/transcribe');
|
||||
|
||||
/// Parse text to structured rapid order.
|
||||
static const ApiEndpoint parseRapidOrder =
|
||||
ApiEndpoint('/core/rapid-orders/parse');
|
||||
ApiEndpoint('/rapid-orders/parse');
|
||||
|
||||
/// Combined transcribe + parse in a single call.
|
||||
static const ApiEndpoint processRapidOrder =
|
||||
ApiEndpoint('/rapid-orders/process');
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ abstract final class StaffEndpoints {
|
||||
/// Benefits.
|
||||
static const ApiEndpoint benefits = ApiEndpoint('/staff/profile/benefits');
|
||||
|
||||
/// Benefits history.
|
||||
static const ApiEndpoint benefitsHistory =
|
||||
ApiEndpoint('/staff/profile/benefits/history');
|
||||
|
||||
/// Time card.
|
||||
static const ApiEndpoint timeCard =
|
||||
ApiEndpoint('/staff/profile/time-card');
|
||||
@@ -112,6 +116,10 @@ abstract final class StaffEndpoints {
|
||||
/// Privacy settings.
|
||||
static const ApiEndpoint privacy = ApiEndpoint('/staff/profile/privacy');
|
||||
|
||||
/// Preferred locations.
|
||||
static const ApiEndpoint locations =
|
||||
ApiEndpoint('/staff/profile/locations');
|
||||
|
||||
/// FAQs.
|
||||
static const ApiEndpoint faqs = ApiEndpoint('/staff/faqs');
|
||||
|
||||
@@ -177,4 +185,16 @@ abstract final class StaffEndpoints {
|
||||
/// Delete certificate by ID.
|
||||
static ApiEndpoint certificateDelete(String certificateId) =>
|
||||
ApiEndpoint('/staff/profile/certificates/$certificateId');
|
||||
|
||||
/// Submit shift for approval.
|
||||
static ApiEndpoint shiftSubmitForApproval(String shiftId) =>
|
||||
ApiEndpoint('/staff/shifts/$shiftId/submit-for-approval');
|
||||
|
||||
/// Location streams.
|
||||
static const ApiEndpoint locationStreams =
|
||||
ApiEndpoint('/staff/location-streams');
|
||||
|
||||
/// Register or delete device push token (POST to register, DELETE to remove).
|
||||
static const ApiEndpoint devicesPushTokens =
|
||||
ApiEndpoint('/staff/devices/push-tokens');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/// Provides the current Firebase ID token for API authentication.
|
||||
///
|
||||
/// Lives in core so feature packages can access auth tokens
|
||||
/// without importing firebase_auth directly.
|
||||
abstract interface class AuthTokenProvider {
|
||||
/// Returns the current ID token, refreshing if expired.
|
||||
///
|
||||
/// Pass [forceRefresh] to force a token refresh from Firebase.
|
||||
/// Returns null if no user is signed in.
|
||||
Future<String?> getIdToken({bool forceRefresh});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
|
||||
import 'package:krow_core/src/services/auth/auth_token_provider.dart';
|
||||
|
||||
/// Firebase-backed implementation of [AuthTokenProvider].
|
||||
///
|
||||
/// Delegates to [FirebaseAuth] to get the current user's
|
||||
/// ID token. Must run in the main isolate (Firebase SDK requirement).
|
||||
class FirebaseAuthTokenProvider implements AuthTokenProvider {
|
||||
@override
|
||||
Future<String?> getIdToken({bool forceRefresh = false}) async {
|
||||
final User? user = FirebaseAuth.instance.currentUser;
|
||||
return user?.getIdToken(forceRefresh);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user