fix: unignore flutter coverage folders and tracking them
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -83,6 +83,8 @@ node_modules/
|
|||||||
dist/
|
dist/
|
||||||
dist-ssr/
|
dist-ssr/
|
||||||
coverage/
|
coverage/
|
||||||
|
!**/lib/**/coverage/
|
||||||
|
!**/src/**/coverage/
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
.vite/
|
.vite/
|
||||||
.temp/
|
.temp/
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
import '../../domain/repositories/coverage_connector_repository.dart';
|
||||||
|
|
||||||
|
/// Implementation of [CoverageConnectorRepository].
|
||||||
|
class CoverageConnectorRepositoryImpl implements CoverageConnectorRepository {
|
||||||
|
CoverageConnectorRepositoryImpl({
|
||||||
|
dc.DataConnectService? service,
|
||||||
|
}) : _service = service ?? dc.DataConnectService.instance;
|
||||||
|
|
||||||
|
final dc.DataConnectService _service;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<CoverageShift>> getShiftsForDate({
|
||||||
|
required String businessId,
|
||||||
|
required DateTime date,
|
||||||
|
}) async {
|
||||||
|
return _service.run(() async {
|
||||||
|
final DateTime start = DateTime(date.year, date.month, date.day);
|
||||||
|
final DateTime end = DateTime(date.year, date.month, date.day, 23, 59, 59, 999);
|
||||||
|
|
||||||
|
final shiftRolesResult = await _service.connector
|
||||||
|
.listShiftRolesByBusinessAndDateRange(
|
||||||
|
businessId: businessId,
|
||||||
|
start: _service.toTimestamp(start),
|
||||||
|
end: _service.toTimestamp(end),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final applicationsResult = await _service.connector
|
||||||
|
.listStaffsApplicationsByBusinessForDay(
|
||||||
|
businessId: businessId,
|
||||||
|
dayStart: _service.toTimestamp(start),
|
||||||
|
dayEnd: _service.toTimestamp(end),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return _mapCoverageShifts(
|
||||||
|
shiftRolesResult.data.shiftRoles,
|
||||||
|
applicationsResult.data.applications,
|
||||||
|
date,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CoverageShift> _mapCoverageShifts(
|
||||||
|
List<dynamic> shiftRoles,
|
||||||
|
List<dynamic> applications,
|
||||||
|
DateTime date,
|
||||||
|
) {
|
||||||
|
if (shiftRoles.isEmpty && applications.isEmpty) return [];
|
||||||
|
|
||||||
|
final Map<String, _CoverageGroup> groups = {};
|
||||||
|
|
||||||
|
for (final sr in shiftRoles) {
|
||||||
|
final String key = '${sr.shiftId}:${sr.roleId}';
|
||||||
|
final startTime = _service.toDateTime(sr.startTime);
|
||||||
|
|
||||||
|
groups[key] = _CoverageGroup(
|
||||||
|
shiftId: sr.shiftId,
|
||||||
|
roleId: sr.roleId,
|
||||||
|
title: sr.role.name,
|
||||||
|
location: sr.shift.location ?? sr.shift.locationAddress ?? '',
|
||||||
|
startTime: startTime != null ? DateFormat('HH:mm').format(startTime) : '00:00',
|
||||||
|
workersNeeded: sr.count,
|
||||||
|
date: _service.toDateTime(sr.shift.date) ?? date,
|
||||||
|
workers: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final app in applications) {
|
||||||
|
final String key = '${app.shiftId}:${app.roleId}';
|
||||||
|
if (!groups.containsKey(key)) {
|
||||||
|
final startTime = _service.toDateTime(app.shiftRole.startTime);
|
||||||
|
groups[key] = _CoverageGroup(
|
||||||
|
shiftId: app.shiftId,
|
||||||
|
roleId: app.roleId,
|
||||||
|
title: app.shiftRole.role.name,
|
||||||
|
location: app.shiftRole.shift.location ?? app.shiftRole.shift.locationAddress ?? '',
|
||||||
|
startTime: startTime != null ? DateFormat('HH:mm').format(startTime) : '00:00',
|
||||||
|
workersNeeded: app.shiftRole.count,
|
||||||
|
date: _service.toDateTime(app.shiftRole.shift.date) ?? date,
|
||||||
|
workers: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final checkIn = _service.toDateTime(app.checkInTime);
|
||||||
|
groups[key]!.workers.add(
|
||||||
|
CoverageWorker(
|
||||||
|
name: app.staff.fullName,
|
||||||
|
status: _mapWorkerStatus(app.status.stringValue),
|
||||||
|
checkInTime: checkIn != null ? DateFormat('HH:mm').format(checkIn) : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups.values
|
||||||
|
.map((g) => CoverageShift(
|
||||||
|
id: '${g.shiftId}:${g.roleId}',
|
||||||
|
title: g.title,
|
||||||
|
location: g.location,
|
||||||
|
startTime: g.startTime,
|
||||||
|
workersNeeded: g.workersNeeded,
|
||||||
|
date: g.date,
|
||||||
|
workers: g.workers,
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
CoverageWorkerStatus _mapWorkerStatus(String status) {
|
||||||
|
switch (status) {
|
||||||
|
case 'PENDING':
|
||||||
|
return CoverageWorkerStatus.pending;
|
||||||
|
case 'REJECTED':
|
||||||
|
return CoverageWorkerStatus.rejected;
|
||||||
|
case 'CONFIRMED':
|
||||||
|
return CoverageWorkerStatus.confirmed;
|
||||||
|
case 'CHECKED_IN':
|
||||||
|
return CoverageWorkerStatus.checkedIn;
|
||||||
|
case 'CHECKED_OUT':
|
||||||
|
return CoverageWorkerStatus.checkedOut;
|
||||||
|
case 'LATE':
|
||||||
|
return CoverageWorkerStatus.late;
|
||||||
|
case 'NO_SHOW':
|
||||||
|
return CoverageWorkerStatus.noShow;
|
||||||
|
case 'COMPLETED':
|
||||||
|
return CoverageWorkerStatus.completed;
|
||||||
|
default:
|
||||||
|
return CoverageWorkerStatus.pending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CoverageGroup {
|
||||||
|
_CoverageGroup({
|
||||||
|
required this.shiftId,
|
||||||
|
required this.roleId,
|
||||||
|
required this.title,
|
||||||
|
required this.location,
|
||||||
|
required this.startTime,
|
||||||
|
required this.workersNeeded,
|
||||||
|
required this.date,
|
||||||
|
required this.workers,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String shiftId;
|
||||||
|
final String roleId;
|
||||||
|
final String title;
|
||||||
|
final String location;
|
||||||
|
final String startTime;
|
||||||
|
final int workersNeeded;
|
||||||
|
final DateTime date;
|
||||||
|
final List<CoverageWorker> workers;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
|
||||||
|
/// Repository interface for coverage connector operations.
|
||||||
|
///
|
||||||
|
/// This acts as a buffer layer between the domain repository and the Data Connect SDK.
|
||||||
|
abstract interface class CoverageConnectorRepository {
|
||||||
|
/// Fetches coverage data for a specific date and business.
|
||||||
|
Future<List<CoverageShift>> getShiftsForDate({
|
||||||
|
required String businessId,
|
||||||
|
required DateTime date,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import '../../../domain/repositories/reports_repository.dart';
|
||||||
|
import 'coverage_event.dart';
|
||||||
|
import 'coverage_state.dart';
|
||||||
|
|
||||||
|
class CoverageBloc extends Bloc<CoverageEvent, CoverageState> {
|
||||||
|
final ReportsRepository _reportsRepository;
|
||||||
|
|
||||||
|
CoverageBloc({required ReportsRepository reportsRepository})
|
||||||
|
: _reportsRepository = reportsRepository,
|
||||||
|
super(CoverageInitial()) {
|
||||||
|
on<LoadCoverageReport>(_onLoadCoverageReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onLoadCoverageReport(
|
||||||
|
LoadCoverageReport event,
|
||||||
|
Emitter<CoverageState> emit,
|
||||||
|
) async {
|
||||||
|
emit(CoverageLoading());
|
||||||
|
try {
|
||||||
|
final report = await _reportsRepository.getCoverageReport(
|
||||||
|
businessId: event.businessId,
|
||||||
|
startDate: event.startDate,
|
||||||
|
endDate: event.endDate,
|
||||||
|
);
|
||||||
|
emit(CoverageLoaded(report));
|
||||||
|
} catch (e) {
|
||||||
|
emit(CoverageError(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class CoverageEvent extends Equatable {
|
||||||
|
const CoverageEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadCoverageReport extends CoverageEvent {
|
||||||
|
final String? businessId;
|
||||||
|
final DateTime startDate;
|
||||||
|
final DateTime endDate;
|
||||||
|
|
||||||
|
const LoadCoverageReport({
|
||||||
|
this.businessId,
|
||||||
|
required this.startDate,
|
||||||
|
required this.endDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [businessId, startDate, endDate];
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
|
||||||
|
abstract class CoverageState extends Equatable {
|
||||||
|
const CoverageState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CoverageInitial extends CoverageState {}
|
||||||
|
|
||||||
|
class CoverageLoading extends CoverageState {}
|
||||||
|
|
||||||
|
class CoverageLoaded extends CoverageState {
|
||||||
|
final CoverageReport report;
|
||||||
|
|
||||||
|
const CoverageLoaded(this.report);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [report];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CoverageError extends CoverageState {
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
const CoverageError(this.message);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [message];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user