feat: Implement GetMyShiftsData use case and integrate it into ShiftsBloc for improved shift data handling

This commit is contained in:
Achintha Isuru
2026-03-19 16:11:16 -04:00
parent 3d80e6b7ac
commit 18a459a453
4 changed files with 86 additions and 22 deletions

View File

@@ -0,0 +1,23 @@
import 'package:krow_domain/krow_domain.dart';
/// Combined result from loading all My Shifts tab data sources.
///
/// Holds assigned shifts, pending assignments, and cancelled shifts
/// fetched in parallel from the V2 API.
class MyShiftsData {
/// Creates a [MyShiftsData] instance.
const MyShiftsData({
required this.assignedShifts,
required this.pendingAssignments,
required this.cancelledShifts,
});
/// Assigned shifts for the requested date range.
final List<AssignedShift> assignedShifts;
/// Pending assignments awaiting worker acceptance.
final List<PendingAssignment> pendingAssignments;
/// Cancelled shift assignments.
final List<CancelledShift> cancelledShifts;
}

View File

@@ -0,0 +1,40 @@
import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
import 'package:staff_shifts/src/domain/arguments/get_my_shifts_arguments.dart';
import 'package:staff_shifts/src/domain/models/my_shifts_data.dart';
import 'package:staff_shifts/src/domain/repositories/shifts_repository_interface.dart';
/// Fetches all data needed for the My Shifts tab in a single call.
///
/// Calls [ShiftsRepositoryInterface.getAssignedShifts],
/// [ShiftsRepositoryInterface.getPendingAssignments], and
/// [ShiftsRepositoryInterface.getCancelledShifts] in parallel and returns
/// a unified [MyShiftsData].
class GetMyShiftsDataUseCase
extends UseCase<GetAssignedShiftsArguments, MyShiftsData> {
/// Creates a [GetMyShiftsDataUseCase].
GetMyShiftsDataUseCase(this._repository);
/// The shifts repository.
final ShiftsRepositoryInterface _repository;
/// Loads assigned, pending, and cancelled shifts for the given date range.
@override
Future<MyShiftsData> call(GetAssignedShiftsArguments arguments) async {
final List<Object> results = await Future.wait(<Future<Object>>[
_repository.getAssignedShifts(
start: arguments.start,
end: arguments.end,
),
_repository.getPendingAssignments(),
_repository.getCancelledShifts(),
]);
return MyShiftsData(
assignedShifts: results[0] as List<AssignedShift>,
pendingAssignments: results[1] as List<PendingAssignment>,
cancelledShifts: results[2] as List<CancelledShift>,
);
}
}

View File

@@ -8,9 +8,11 @@ import 'package:staff_shifts/src/domain/arguments/get_available_shifts_arguments
import 'package:staff_shifts/src/domain/arguments/get_my_shifts_arguments.dart';
import 'package:staff_shifts/src/domain/usecases/accept_shift_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/decline_shift_usecase.dart';
import 'package:staff_shifts/src/domain/models/my_shifts_data.dart';
import 'package:staff_shifts/src/domain/usecases/get_available_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_cancelled_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_history_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_my_shifts_data_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_my_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_pending_assignments_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_profile_completion_usecase.dart';
@@ -34,6 +36,7 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState>
required this.acceptShift,
required this.declineShift,
required this.submitForApproval,
required this.getMyShiftsData,
}) : super(const ShiftsState()) {
on<LoadShiftsEvent>(_onLoadShifts);
on<LoadHistoryShiftsEvent>(_onLoadHistoryShifts);
@@ -74,6 +77,9 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState>
/// Use case for submitting a shift for timesheet approval.
final SubmitForApprovalUseCase submitForApproval;
/// Use case that loads assigned, pending, and cancelled shifts in parallel.
final GetMyShiftsDataUseCase getMyShiftsData;
Future<void> _onLoadShifts(
LoadShiftsEvent event,
Emitter<ShiftsState> emit,
@@ -86,29 +92,16 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState>
emit: emit.call,
action: () async {
final List<DateTime> days = getCalendarDaysForOffset(0);
// Load assigned, pending, and cancelled shifts in parallel.
final List<Object> results = await Future.wait(<Future<Object>>[
getAssignedShifts(
final MyShiftsData data = await getMyShiftsData(
GetAssignedShiftsArguments(start: days.first, end: days.last),
),
getPendingAssignments(),
getCancelledShifts(),
]);
final List<AssignedShift> myShiftsResult =
results[0] as List<AssignedShift>;
final List<PendingAssignment> pendingResult =
results[1] as List<PendingAssignment>;
final List<CancelledShift> cancelledResult =
results[2] as List<CancelledShift>;
);
emit(
state.copyWith(
status: ShiftsStatus.loaded,
myShifts: myShiftsResult,
pendingShifts: pendingResult,
cancelledShifts: cancelledResult,
myShifts: data.assignedShifts,
pendingShifts: data.pendingAssignments,
cancelledShifts: data.cancelledShifts,
availableShifts: const <OpenShift>[],
historyShifts: const <CompletedShift>[],
availableLoading: false,
@@ -250,18 +243,23 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState>
LoadShiftsForRangeEvent event,
Emitter<ShiftsState> emit,
) async {
emit(state.copyWith(myShifts: const <AssignedShift>[], myShiftsLoaded: false));
emit(state.copyWith(
myShifts: const <AssignedShift>[],
myShiftsLoaded: false,
));
await handleError(
emit: emit.call,
action: () async {
final List<AssignedShift> myShiftsResult = await getAssignedShifts(
final MyShiftsData data = await getMyShiftsData(
GetAssignedShiftsArguments(start: event.start, end: event.end),
);
emit(
state.copyWith(
status: ShiftsStatus.loaded,
myShifts: myShiftsResult,
myShifts: data.assignedShifts,
pendingShifts: data.pendingAssignments,
cancelledShifts: data.cancelledShifts,
myShiftsLoaded: true,
clearErrorMessage: true,
),

View File

@@ -8,6 +8,7 @@ import 'package:staff_shifts/src/domain/usecases/apply_for_shift_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_available_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_cancelled_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_history_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_my_shifts_data_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_my_shifts_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_pending_assignments_usecase.dart';
import 'package:staff_shifts/src/domain/usecases/get_profile_completion_usecase.dart';
@@ -52,6 +53,7 @@ class StaffShiftsModule extends Module {
i.addLazySingleton(
() => SubmitForApprovalUseCase(i.get<ShiftsRepositoryInterface>()),
);
i.addLazySingleton(GetMyShiftsDataUseCase.new);
i.addLazySingleton(GetAvailableOrdersUseCase.new);
i.addLazySingleton(BookOrderUseCase.new);
@@ -67,6 +69,7 @@ class StaffShiftsModule extends Module {
acceptShift: i.get(),
declineShift: i.get(),
submitForApproval: i.get(),
getMyShiftsData: i.get(),
),
);
i.add(